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