1//! # panel
2use gpui::actions;
3use ui::{prelude::*, Tab};
4
5actions!(panel, [NextPanelTab, PreviousPanelTab]);
6
7pub trait PanelHeader: workspace::Panel {
8 fn header_height(&self, cx: &mut App) -> Pixels {
9 Tab::container_height(cx)
10 }
11
12 fn panel_header_container(&self, _window: &mut Window, cx: &mut App) -> Div {
13 h_flex()
14 .h(self.header_height(cx))
15 .w_full()
16 .px_1()
17 .flex_none()
18 .border_b_1()
19 .border_color(cx.theme().colors().border)
20 }
21}
22
23/// Implement this trait to enable a panel to have tabs.
24pub trait PanelTabs: PanelHeader {
25 /// Returns the index of the currently selected tab.
26 fn selected_tab(&self, cx: &mut App) -> usize;
27 /// Selects the tab at the given index.
28 fn select_tab(&self, cx: &mut App, index: usize);
29 /// Moves to the next tab.
30 fn next_tab(&self, _: NextPanelTab, cx: &mut App) -> Self;
31 /// Moves to the previous tab.
32 fn previous_tab(&self, _: PreviousPanelTab, cx: &mut App) -> Self;
33}
34
35#[derive(IntoElement)]
36pub struct PanelTab {}
37
38impl RenderOnce for PanelTab {
39 fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
40 div()
41 }
42}
43
44pub fn panel_button(label: impl Into<SharedString>) -> ui::Button {
45 let label = label.into();
46 let id = ElementId::Name(label.clone().to_lowercase().replace(' ', "_").into());
47 ui::Button::new(id, label)
48 .label_size(ui::LabelSize::Small)
49 .layer(ui::ElevationIndex::Surface)
50 .size(ui::ButtonSize::Compact)
51}
52
53pub fn panel_filled_button(label: impl Into<SharedString>) -> ui::Button {
54 panel_button(label).style(ui::ButtonStyle::Filled)
55}
56
57pub fn panel_icon_button(id: impl Into<SharedString>, icon: IconName) -> ui::IconButton {
58 let id = ElementId::Name(id.into());
59 ui::IconButton::new(id, icon)
60 .layer(ui::ElevationIndex::Surface)
61 .size(ui::ButtonSize::Compact)
62}
63
64pub fn panel_filled_icon_button(id: impl Into<SharedString>, icon: IconName) -> ui::IconButton {
65 panel_icon_button(id, icon).style(ui::ButtonStyle::Filled)
66}