@@ -21,6 +21,7 @@ pub struct TerminalPanel {
impl TerminalPanel {
pub fn new(workspace: &Workspace, cx: &mut ViewContext<Self>) -> Self {
+ let this = cx.weak_handle();
let pane = cx.add_view(|cx| {
let window_id = cx.window_id();
let mut pane = Pane::new(
@@ -36,6 +37,23 @@ impl TerminalPanel {
item.handle.act_as::<TerminalView>(cx).is_some()
})
});
+ pane.set_render_tab_bar_buttons(cx, move |_, cx| {
+ let this = this.clone();
+ Pane::render_tab_bar_button(
+ 0,
+ "icons/plus_12.svg",
+ cx,
+ move |_, cx| {
+ let this = this.clone();
+ cx.window_context().defer(move |cx| {
+ if let Some(this) = this.upgrade(cx) {
+ this.update(cx, |this, cx| this.add_terminal(cx));
+ }
+ })
+ },
+ None,
+ )
+ });
pane
});
let subscriptions = vec![
@@ -61,6 +79,33 @@ impl TerminalPanel {
_ => {}
}
}
+
+ fn add_terminal(&mut self, cx: &mut ViewContext<Self>) {
+ if let Some(workspace) = self.workspace.upgrade(cx) {
+ let working_directory_strategy = cx
+ .global::<Settings>()
+ .terminal_overrides
+ .working_directory
+ .clone()
+ .unwrap_or(WorkingDirectory::CurrentProjectDirectory);
+ let working_directory =
+ crate::get_working_directory(workspace.read(cx), cx, working_directory_strategy);
+ let window_id = cx.window_id();
+ if let Some(terminal) = self.project.update(cx, |project, cx| {
+ project
+ .create_terminal(working_directory, window_id, cx)
+ .log_err()
+ }) {
+ workspace.update(cx, |workspace, cx| {
+ let terminal =
+ Box::new(cx.add_view(|cx| {
+ TerminalView::new(terminal, workspace.database_id(), cx)
+ }));
+ Pane::add_item(workspace, &self.pane, terminal, true, true, None, cx);
+ });
+ }
+ }
+ }
}
impl Entity for TerminalPanel {
@@ -78,32 +123,7 @@ impl View for TerminalPanel {
fn focus_in(&mut self, _: gpui::AnyViewHandle, cx: &mut ViewContext<Self>) {
if self.pane.read(cx).items_len() == 0 {
- if let Some(workspace) = self.workspace.upgrade(cx) {
- let working_directory_strategy = cx
- .global::<Settings>()
- .terminal_overrides
- .working_directory
- .clone()
- .unwrap_or(WorkingDirectory::CurrentProjectDirectory);
- let working_directory = crate::get_working_directory(
- workspace.read(cx),
- cx,
- working_directory_strategy,
- );
- let window_id = cx.window_id();
- if let Some(terminal) = self.project.update(cx, |project, cx| {
- project
- .create_terminal(working_directory, window_id, cx)
- .log_err()
- }) {
- workspace.update(cx, |workspace, cx| {
- let terminal = Box::new(cx.add_view(|cx| {
- TerminalView::new(terminal, workspace.database_id(), cx)
- }));
- Pane::add_item(workspace, &self.pane, terminal, true, true, None, cx);
- });
- }
- }
+ self.add_terminal(cx)
}
}
}
@@ -150,6 +150,7 @@ pub struct Pane {
has_focus: bool,
can_drop: Rc<dyn Fn(&DragAndDrop<Workspace>, &WindowContext) -> bool>,
can_split: bool,
+ render_tab_bar_buttons: Rc<dyn Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>>,
}
pub struct ItemNavHistory {
@@ -257,6 +258,27 @@ impl Pane {
has_focus: false,
can_drop: Rc::new(|_, _| true),
can_split: true,
+ render_tab_bar_buttons: Rc::new(|pane, cx| {
+ Flex::row()
+ // New menu
+ .with_child(Self::render_tab_bar_button(
+ 0,
+ "icons/plus_12.svg",
+ cx,
+ |pane, cx| pane.deploy_new_menu(cx),
+ pane.tab_bar_context_menu
+ .handle_if_kind(TabBarContextMenuKind::New),
+ ))
+ .with_child(Self::render_tab_bar_button(
+ 2,
+ "icons/split_12.svg",
+ cx,
+ |pane, cx| pane.deploy_split_menu(cx),
+ pane.tab_bar_context_menu
+ .handle_if_kind(TabBarContextMenuKind::Split),
+ ))
+ .into_any()
+ }),
}
}
@@ -289,6 +311,14 @@ impl Pane {
cx.notify();
}
+ pub fn set_render_tab_bar_buttons<F>(&mut self, cx: &mut ViewContext<Self>, render: F)
+ where
+ F: 'static + Fn(&mut Pane, &mut ViewContext<Pane>) -> AnyElement<Pane>,
+ {
+ self.render_tab_bar_buttons = Rc::new(render);
+ cx.notify();
+ }
+
pub fn nav_history_for_item<T: Item>(&self, item: &ViewHandle<T>) -> ItemNavHistory {
ItemNavHistory {
history: self.nav_history.clone(),
@@ -1475,33 +1505,37 @@ impl Pane {
.into_any()
}
- fn render_tab_bar_buttons(
- &mut self,
- theme: &Theme,
- cx: &mut ViewContext<Self>,
- ) -> AnyElement<Self> {
- Flex::row()
- // New menu
- .with_child(render_tab_bar_button(
- 0,
- "icons/plus_12.svg",
- cx,
- |pane, cx| pane.deploy_new_menu(cx),
- self.tab_bar_context_menu
- .handle_if_kind(TabBarContextMenuKind::New),
- ))
- .with_child(render_tab_bar_button(
- 2,
- "icons/split_12.svg",
- cx,
- |pane, cx| pane.deploy_split_menu(cx),
- self.tab_bar_context_menu
- .handle_if_kind(TabBarContextMenuKind::Split),
- ))
- .contained()
- .with_style(theme.workspace.tab_bar.pane_button_container)
+ pub fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
+ index: usize,
+ icon: &'static str,
+ cx: &mut ViewContext<Pane>,
+ on_click: F,
+ context_menu: Option<ViewHandle<ContextMenu>>,
+ ) -> AnyElement<Pane> {
+ enum TabBarButton {}
+
+ Stack::new()
+ .with_child(
+ MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
+ let theme = &cx.global::<Settings>().theme.workspace.tab_bar;
+ let style = theme.pane_button.style_for(mouse_state, false);
+ Svg::new(icon)
+ .with_color(style.color)
+ .constrained()
+ .with_width(style.icon_width)
+ .aligned()
+ .constrained()
+ .with_width(style.button_width)
+ .with_height(style.button_width)
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)),
+ )
+ .with_children(
+ context_menu.map(|menu| ChildView::new(&menu, cx).aligned().bottom().right()),
+ )
.flex(1., false)
- .into_any()
+ .into_any_named("tab bar button")
}
fn render_blank_pane(&self, theme: &Theme, _cx: &mut ViewContext<Self>) -> AnyElement<Self> {
@@ -1554,7 +1588,14 @@ impl View for Pane {
.with_child(self.render_tabs(cx).flex(1., true).into_any_named("tabs"));
if self.is_active {
- tab_row.add_child(self.render_tab_bar_buttons(&theme, cx))
+ let render_tab_bar_buttons = self.render_tab_bar_buttons.clone();
+ tab_row.add_child(
+ (render_tab_bar_buttons)(self, cx)
+ .contained()
+ .with_style(theme.workspace.tab_bar.pane_button_container)
+ .flex(1., false)
+ .into_any(),
+ )
}
stack.add_child(tab_row);
@@ -1676,39 +1717,6 @@ impl View for Pane {
}
}
-fn render_tab_bar_button<F: 'static + Fn(&mut Pane, &mut EventContext<Pane>)>(
- index: usize,
- icon: &'static str,
- cx: &mut ViewContext<Pane>,
- on_click: F,
- context_menu: Option<ViewHandle<ContextMenu>>,
-) -> AnyElement<Pane> {
- enum TabBarButton {}
-
- Stack::new()
- .with_child(
- MouseEventHandler::<TabBarButton, _>::new(index, cx, |mouse_state, cx| {
- let theme = &cx.global::<Settings>().theme.workspace.tab_bar;
- let style = theme.pane_button.style_for(mouse_state, false);
- Svg::new(icon)
- .with_color(style.color)
- .constrained()
- .with_width(style.icon_width)
- .aligned()
- .constrained()
- .with_width(style.button_width)
- .with_height(style.button_width)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click(MouseButton::Left, move |_, pane, cx| on_click(pane, cx)),
- )
- .with_children(
- context_menu.map(|menu| ChildView::new(&menu, cx).aligned().bottom().right()),
- )
- .flex(1., false)
- .into_any_named("tab bar button")
-}
-
impl ItemNavHistory {
pub fn push<D: 'static + Any>(&self, data: Option<D>, cx: &mut WindowContext) {
self.history.borrow_mut().push(data, self.item.clone(), cx);