panel.rs

  1//! # panel
  2use editor::{Editor, EditorElement, EditorStyle};
  3use gpui::{Entity, TextStyle, actions};
  4use settings::Settings;
  5use theme::ThemeSettings;
  6use ui::{Tab, prelude::*};
  7
  8actions!(
  9    panel,
 10    [
 11        /// Navigates to the next tab in the panel.
 12        NextPanelTab,
 13        /// Navigates to the previous tab in the panel.
 14        PreviousPanelTab
 15    ]
 16);
 17
 18pub trait PanelHeader: workspace::Panel {
 19    fn header_height(&self, cx: &mut App) -> Pixels {
 20        Tab::container_height(cx)
 21    }
 22
 23    fn panel_header_container(&self, _window: &mut Window, cx: &mut App) -> Div {
 24        h_flex()
 25            .h(self.header_height(cx))
 26            .w_full()
 27            .px_1()
 28            .flex_none()
 29    }
 30}
 31
 32/// Implement this trait to enable a panel to have tabs.
 33pub trait PanelTabs: PanelHeader {
 34    /// Returns the index of the currently selected tab.
 35    fn selected_tab(&self, cx: &mut App) -> usize;
 36    /// Selects the tab at the given index.
 37    fn select_tab(&self, cx: &mut App, index: usize);
 38    /// Moves to the next tab.
 39    fn next_tab(&self, _: NextPanelTab, cx: &mut App) -> Self;
 40    /// Moves to the previous tab.
 41    fn previous_tab(&self, _: PreviousPanelTab, cx: &mut App) -> Self;
 42}
 43
 44#[derive(IntoElement)]
 45pub struct PanelTab {}
 46
 47impl RenderOnce for PanelTab {
 48    fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
 49        div()
 50    }
 51}
 52
 53pub fn panel_button(label: impl Into<SharedString>) -> ui::Button {
 54    let label = label.into();
 55    let id = ElementId::Name(label.to_lowercase().replace(' ', "_").into());
 56    ui::Button::new(id, label)
 57        .label_size(ui::LabelSize::Small)
 58        .icon_size(ui::IconSize::Small)
 59        // TODO: Change this once we use on_surface_bg in button_like
 60        .layer(ui::ElevationIndex::ModalSurface)
 61        .size(ui::ButtonSize::Compact)
 62}
 63
 64pub fn panel_filled_button(label: impl Into<SharedString>) -> ui::Button {
 65    panel_button(label).style(ui::ButtonStyle::Filled)
 66}
 67
 68pub fn panel_icon_button(id: impl Into<SharedString>, icon: IconName) -> ui::IconButton {
 69    let id = ElementId::Name(id.into());
 70
 71    IconButton::new(id, icon)
 72        // TODO: Change this once we use on_surface_bg in button_like
 73        .layer(ui::ElevationIndex::ModalSurface)
 74}
 75
 76pub fn panel_filled_icon_button(id: impl Into<SharedString>, icon: IconName) -> ui::IconButton {
 77    panel_icon_button(id, icon).style(ui::ButtonStyle::Filled)
 78}
 79
 80pub fn panel_editor_container(_window: &mut Window, cx: &mut App) -> Div {
 81    v_flex()
 82        .size_full()
 83        .gap(px(8.))
 84        .p_2()
 85        .bg(cx.theme().colors().editor_background)
 86}
 87
 88pub fn panel_editor_style(monospace: bool, window: &Window, cx: &App) -> EditorStyle {
 89    let settings = ThemeSettings::get_global(cx);
 90
 91    let font_size = TextSize::Small.rems(cx).to_pixels(window.rem_size());
 92
 93    let (font_family, font_fallbacks, font_features, font_weight, line_height) = if monospace {
 94        (
 95            settings.buffer_font.family.clone(),
 96            settings.buffer_font.fallbacks.clone(),
 97            settings.buffer_font.features.clone(),
 98            settings.buffer_font.weight,
 99            font_size * settings.buffer_line_height.value(),
100        )
101    } else {
102        (
103            settings.ui_font.family.clone(),
104            settings.ui_font.fallbacks.clone(),
105            settings.ui_font.features.clone(),
106            settings.ui_font.weight,
107            window.line_height(),
108        )
109    };
110
111    EditorStyle {
112        background: cx.theme().colors().editor_background,
113        local_player: cx.theme().players().local(),
114        text: TextStyle {
115            color: cx.theme().colors().text,
116            font_family,
117            font_fallbacks,
118            font_features,
119            font_size: TextSize::Small.rems(cx).into(),
120            font_weight,
121            line_height: line_height.into(),
122            ..Default::default()
123        },
124        syntax: cx.theme().syntax().clone(),
125        ..Default::default()
126    }
127}
128
129pub fn panel_editor_element(
130    editor: &Entity<Editor>,
131    monospace: bool,
132    window: &mut Window,
133    cx: &mut App,
134) -> EditorElement {
135    EditorElement::new(editor, panel_editor_style(monospace, window, cx))
136}