@@ -1,26 +1,26 @@
+use context_menu::{ContextMenu, ContextMenuItem};
use gpui::{
- elements::{Empty, MouseEventHandler, Svg},
- CursorStyle, Element, ElementBox, Entity, MouseButton, RenderContext, View, ViewContext,
- ViewHandle, WeakViewHandle,
+ actions, elements::*, geometry::vector::vec2f, CursorStyle, Element, ElementBox, Entity,
+ MouseButton, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, WeakViewHandle,
};
use settings::Settings;
-use crate::{dock::FocusDock, item::ItemHandle, StatusItemView, Workspace};
+use crate::{dock::FocusDock, item::ItemHandle, NewTerminal, StatusItemView, Workspace};
-pub struct TerminalButton {
- workspace: WeakViewHandle<Workspace>,
-}
+// #[derive(Clone, PartialEq)]
+// pub struct DeployTerminalMenu {
+// position: Vector2F,
+// }
-// TODO: Rename this to `DeployTerminalButton`
-impl TerminalButton {
- pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
- // When terminal moves, redraw so that the icon and toggle status matches.
- cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
+actions!(terminal, [DeployTerminalMenu]);
- Self {
- workspace: workspace.downgrade(),
- }
- }
+pub fn init(cx: &mut MutableAppContext) {
+ cx.add_action(TerminalButton::deploy_terminal_menu);
+}
+
+pub struct TerminalButton {
+ workspace: WeakViewHandle<Workspace>,
+ popup_menu: ViewHandle<ContextMenu>,
}
impl Entity for TerminalButton {
@@ -34,52 +34,93 @@ impl View for TerminalButton {
fn render(&mut self, cx: &mut RenderContext<'_, Self>) -> ElementBox {
let workspace = self.workspace.upgrade(cx);
+ let project = match workspace {
+ Some(workspace) => workspace.read(cx).project().read(cx),
+ None => return Empty::new().boxed(),
+ };
+ let has_terminals = !project.local_terminal_handles().is_empty();
+ let terminal_count = project.local_terminal_handles().iter().count();
+ let theme = cx.global::<Settings>().theme.clone();
- if workspace.is_none() {
- return Empty::new().boxed();
- }
+ Stack::new()
+ .with_child(
+ MouseEventHandler::<Self>::new(0, cx, {
+ let theme = theme.clone();
+ move |state, _| {
+ let style = theme
+ .workspace
+ .status_bar
+ .sidebar_buttons
+ .item
+ .style_for(state, true);
- // let workspace = workspace.unwrap();
- let theme = cx.global::<Settings>().theme.clone();
+ Svg::new("icons/terminal_12.svg")
+ .with_color(style.icon_color)
+ .constrained()
+ .with_width(style.icon_size)
+ .with_height(style.icon_size)
+ .contained()
+ .with_style(style.container)
+ .boxed()
+ }
+ })
+ .with_cursor_style(CursorStyle::PointingHand)
+ .on_up(MouseButton::Left, move |_, _| {
+ // TODO: Do we need this stuff?
+ // let dock_pane = workspace.read(cx.app).dock_pane();
+ // let drop_index = dock_pane.read(cx.app).items_len() + 1;
+ // handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);
+ })
+ .on_click(MouseButton::Left, move |_, cx| {
+ if has_terminals {
+ cx.dispatch_action(DeployTerminalMenu);
+ println!("Yes, has_terminals {}", terminal_count);
+ } else {
+ cx.dispatch_action(FocusDock);
+ };
+ })
+ .with_tooltip::<Self, _>(
+ 0,
+ "Show Terminal".into(),
+ Some(Box::new(FocusDock)),
+ theme.tooltip.clone(),
+ cx,
+ )
+ .boxed(),
+ )
+ .with_child(ChildView::new(&self.popup_menu, cx).boxed())
+ .boxed()
+ }
+}
- MouseEventHandler::<Self>::new(0, cx, {
- let theme = theme.clone();
- move |state, _| {
- let style = theme
- .workspace
- .status_bar
- .sidebar_buttons
- .item
- .style_for(state, true);
+// TODO: Rename this to `DeployTerminalButton`
+impl TerminalButton {
+ pub fn new(workspace: ViewHandle<Workspace>, cx: &mut ViewContext<Self>) -> Self {
+ // When terminal moves, redraw so that the icon and toggle status matches.
+ cx.subscribe(&workspace, |_, _, _, cx| cx.notify()).detach();
+ Self {
+ workspace: workspace.downgrade(),
+ popup_menu: cx.add_view(|cx| {
+ let mut menu = ContextMenu::new(cx);
+ menu.set_position_mode(OverlayPositionMode::Local);
+ menu
+ }),
+ }
+ }
- Svg::new("icons/terminal_12.svg")
- .with_color(style.icon_color)
- .constrained()
- .with_width(style.icon_size)
- .with_height(style.icon_size)
- .contained()
- .with_style(style.container)
- .boxed()
- }
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_up(MouseButton::Left, move |_, _| {
- // TODO: Do we need this stuff?
- // let dock_pane = workspace.read(cx.app).dock_pane();
- // let drop_index = dock_pane.read(cx.app).items_len() + 1;
- // handle_dropped_item(event, &dock_pane.downgrade(), drop_index, false, None, cx);
- })
- .on_click(MouseButton::Left, |_, cx| {
- cx.dispatch_action(FocusDock);
- })
- .with_tooltip::<Self, _>(
- 0,
- "Show Terminal".into(),
- Some(Box::new(FocusDock)),
- theme.tooltip.clone(),
- cx,
- )
- .boxed()
+ pub fn deploy_terminal_menu(
+ &mut self,
+ _action: &DeployTerminalMenu,
+ cx: &mut ViewContext<Self>,
+ ) {
+ self.popup_menu.update(cx, |menu, cx| {
+ menu.show(
+ vec2f(0., 0.),
+ AnchorCorner::TopLeft,
+ vec![ContextMenuItem::item("New Terminal", NewTerminal)],
+ cx,
+ );
+ });
}
}