339 lines · 11.4 KB · Rust
RawDownload
use crate::KeyBinding;use crate::prelude::*;use gpui::{AnyElement, App, BoxShadow, FontStyle, Hsla, IntoElement, Window, point};use theme::Appearance; /// Represents a hint for a keybinding, optionally with a prefix and suffix.////// This struct allows for the creation and customization of a keybinding hint,/// which can be used to display keyboard shortcuts or commands in a user interface.////// # Examples////// ```no_run/// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};/// use ui::prelude::*;/// use ui::{KeyBinding, KeybindingHint};/// use settings::KeybindSource;////// # fn example(cx: &App) {/// let hint = KeybindingHint::new(///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-s").unwrap())].into(), KeybindSource::Base),///     Hsla::black()/// )///     .prefix("Save:")///     .size(Pixels::from(14.0));/// # }/// ```#[derive(Debug, IntoElement, RegisterComponent)]pub struct KeybindingHint {    prefix: Option<SharedString>,    suffix: Option<SharedString>,    keybinding: KeyBinding,    size: Option<Pixels>,    background_color: Hsla,} impl KeybindingHint {    /// Creates a new `KeybindingHint` with the specified keybinding.    ///    /// This method initializes a new `KeybindingHint` instance with the given keybinding,    /// setting all other fields to their default values.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::new(    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())].into(), KeybindSource::Base),    ///     Hsla::black()    /// );    /// # }    /// ```    pub fn new(keybinding: KeyBinding, background_color: Hsla) -> Self {        Self {            prefix: None,            suffix: None,            keybinding,            size: None,            background_color,        }    }     /// Creates a new `KeybindingHint` with a prefix and keybinding.    ///    /// This method initializes a new `KeybindingHint` instance with the given prefix and keybinding,    /// setting all other fields to their default values.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::with_prefix(    ///     "Copy:",    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-c").unwrap())].into(), KeybindSource::Base),    ///     Hsla::black()    /// );    /// # }    /// ```    pub fn with_prefix(        prefix: impl Into<SharedString>,        keybinding: KeyBinding,        background_color: Hsla,    ) -> Self {        Self {            prefix: Some(prefix.into()),            suffix: None,            keybinding,            size: None,            background_color,        }    }     /// Creates a new `KeybindingHint` with a keybinding and suffix.    ///    /// This method initializes a new `KeybindingHint` instance with the given keybinding and suffix,    /// setting all other fields to their default values.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::with_suffix(    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-v").unwrap())].into(), KeybindSource::Base),    ///     "Paste",    ///     Hsla::black()    /// );    /// # }    /// ```    pub fn with_suffix(        keybinding: KeyBinding,        suffix: impl Into<SharedString>,        background_color: Hsla,    ) -> Self {        Self {            prefix: None,            suffix: Some(suffix.into()),            keybinding,            size: None,            background_color,        }    }     /// Sets the prefix for the keybinding hint.    ///    /// This method allows adding or changing the prefix text that appears before the keybinding.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::new(    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-x").unwrap())].into(), KeybindSource::Base),    ///     Hsla::black()    /// )    ///     .prefix("Cut:");    /// # }    /// ```    pub fn prefix(mut self, prefix: impl Into<SharedString>) -> Self {        self.prefix = Some(prefix.into());        self    }     /// Sets the suffix for the keybinding hint.    ///    /// This method allows adding or changing the suffix text that appears after the keybinding.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::new(    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-f").unwrap())].into(), KeybindSource::Base),    ///     Hsla::black()    /// )    ///     .suffix("Find");    /// # }    /// ```    pub fn suffix(mut self, suffix: impl Into<SharedString>) -> Self {        self.suffix = Some(suffix.into());        self    }     /// Sets the size of the keybinding hint.    ///    /// This method allows specifying the size of the keybinding hint in pixels.    ///    /// # Examples    ///    /// ```no_run    /// use gpui::{App, Hsla, KeybindingKeystroke, Keystroke};    /// use ui::prelude::*;    /// use ui::{KeyBinding, KeybindingHint};    /// use settings::KeybindSource;    ///    /// # fn example(cx: &App) {    /// let hint = KeybindingHint::new(    ///     KeyBinding::from_keystrokes(vec![KeybindingKeystroke::from_keystroke(Keystroke::parse("ctrl-z").unwrap())].into(), KeybindSource::Base),    ///     Hsla::black()    /// )    ///     .size(Pixels::from(16.0));    /// # }    /// ```    pub fn size(mut self, size: impl Into<Option<Pixels>>) -> Self {        self.size = size.into();        self    }} impl RenderOnce for KeybindingHint {    fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {        let colors = cx.theme().colors();        let is_light = cx.theme().appearance() == Appearance::Light;         let border_color =            self.background_color                .blend(colors.text.alpha(if is_light { 0.08 } else { 0.16 }));         let bg_color = self            .background_color            .blend(colors.text_accent.alpha(if is_light { 0.05 } else { 0.1 }));         let shadow_color = colors.text.alpha(if is_light { 0.04 } else { 0.08 });         let size = self            .size            .unwrap_or(TextSize::Small.rems(cx).to_pixels(window.rem_size()));         let kb_size = size - px(2.0);         let mut base = h_flex();         base.text_style().font_style = Some(FontStyle::Italic);         base.gap_1()            .font_buffer(cx)            .text_size(size)            .text_color(colors.text_disabled)            .children(self.prefix)            .child(                h_flex()                    .rounded_sm()                    .px_0p5()                    .mr_0p5()                    .border_1()                    .border_color(border_color)                    .bg(bg_color)                    .shadow(vec![BoxShadow {                        color: shadow_color,                        offset: point(px(0.), px(1.)),                        blur_radius: px(0.),                        spread_radius: px(0.),                    }])                    .child(self.keybinding.size(rems_from_px(kb_size))),            )            .children(self.suffix)    }} impl Component for KeybindingHint {    fn scope() -> ComponentScope {        ComponentScope::DataDisplay    }     fn description() -> Option<&'static str> {        Some("Displays a keyboard shortcut hint with optional prefix and suffix text")    }     fn preview(_window: &mut Window, cx: &mut App) -> Option<AnyElement> {        let enter = KeyBinding::for_action(&menu::Confirm, cx);         let bg_color = cx.theme().colors().surface_background;         Some(            v_flex()                .gap_6()                .children(vec![                    example_group_with_title(                        "Basic",                        vec![                            single_example(                                "With Prefix",                                KeybindingHint::with_prefix(                                    "Go to Start:",                                    enter.clone(),                                    bg_color,                                )                                .into_any_element(),                            ),                            single_example(                                "With Suffix",                                KeybindingHint::with_suffix(enter.clone(), "Go to End", bg_color)                                    .into_any_element(),                            ),                            single_example(                                "With Prefix and Suffix",                                KeybindingHint::new(enter.clone(), bg_color)                                    .prefix("Confirm:")                                    .suffix("Execute selected action")                                    .into_any_element(),                            ),                        ],                    ),                    example_group_with_title(                        "Sizes",                        vec![                            single_example(                                "Small",                                KeybindingHint::new(enter.clone(), bg_color)                                    .size(Pixels::from(12.0))                                    .prefix("Small:")                                    .into_any_element(),                            ),                            single_example(                                "Medium",                                KeybindingHint::new(enter.clone(), bg_color)                                    .size(Pixels::from(16.0))                                    .suffix("Medium")                                    .into_any_element(),                            ),                            single_example(                                "Large",                                KeybindingHint::new(enter, bg_color)                                    .size(Pixels::from(20.0))                                    .prefix("Large:")                                    .suffix("Size")                                    .into_any_element(),                            ),                        ],                    ),                ])                .into_any_element(),        )    }}