ui/components/pane/
render.rs1use gpui::Empty;
5
6use super::{Pane, PaneEvent};
7use crate::{IconButton, IconName, IconSize, Tab, TabBar, prelude::*};
8
9fn debug_wrap(id: impl Into<ElementId>, selector: String, child: IconButton) -> impl IntoElement {
15 div().id(id).debug_selector(move || selector).child(child)
16}
17
18#[derive(Clone, Copy)]
20struct TabDragPayload {
21 from_idx: usize,
22}
23
24impl Render for Pane {
25 fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
26 let active_idx = self.active_idx;
27 let mut tab_bar = TabBar::new("pane-tab-bar");
28
29 for ix in 0..self.tabs.len() {
30 let tab_id = self.tabs[ix].0;
31 let title = self.tabs[ix].1.title();
32 let selected = ix == active_idx;
33
34 let hover_group = SharedString::from(format!("pane-tab-{}", tab_id.0));
38 let mut close_ib = IconButton::new(("pane-tab-close", tab_id.0), IconName::Close)
41 .icon_size(IconSize::XSmall)
42 .on_click(cx.listener(move |this, _, _, cx| {
43 this.close_tab(ix, cx);
44 }));
45 if !selected {
46 close_ib = close_ib.visible_on_hover(hover_group.clone());
47 }
48 let close_button = debug_wrap(
49 ("pane-tab-close-wrap", tab_id.0),
50 format!("PANE-TAB-CLOSE-{}", tab_id.0),
51 close_ib,
52 );
53
54 let tab = Tab::new(("pane-tab", tab_id.0))
55 .group(hover_group)
56 .toggle_state(selected)
57 .end_slot(close_button)
58 .child(Label::new(title).size(LabelSize::Small))
63 .on_click(cx.listener(move |this, _, _, cx| {
64 this.activate(ix, cx);
65 }))
66 .on_drag(TabDragPayload { from_idx: ix }, |_, _, _, cx| {
67 cx.new(|_| Empty)
68 })
69 .drag_over::<TabDragPayload>(|style, _, _, _| style.opacity(0.5))
70 .on_drop(cx.listener(move |this, payload: &TabDragPayload, _, cx| {
71 this.reorder(payload.from_idx, ix, cx);
72 }));
73
74 tab_bar = tab_bar.child(tab);
75 }
76
77 tab_bar = tab_bar.end_child(debug_wrap(
78 "pane-add-tab-wrap",
79 "PANE-ADD-TAB".to_string(),
80 IconButton::new("pane-add-tab", IconName::Plus)
81 .icon_size(IconSize::XSmall)
82 .on_click(cx.listener(|this, _, _, cx| {
83 let content = (this.new_tab_factory)();
84 this.add_tab(content, cx);
85 })),
86 ));
87
88 tab_bar = tab_bar.end_child(debug_wrap(
91 "pane-close-wrap",
92 "PANE-CLOSE".to_string(),
93 IconButton::new("pane-close", IconName::Close)
94 .icon_size(IconSize::XSmall)
95 .on_click(cx.listener(|_, _, _, cx| {
96 cx.emit(PaneEvent::CloseRequested);
97 })),
98 ));
99
100 let content = self
101 .tabs
102 .get(active_idx)
103 .map(|(_, content)| content.render(true, window, cx));
104
105 v_flex()
106 .id("pane")
107 .size_full()
108 .child(tab_bar)
109 .child(div().flex_1().min_h_0().overflow_hidden().children(content))
110 }
111}