From a4a501603e24585280ade2133f9209dc78c2a6ec Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 12 Dec 2023 13:11:54 -0800 Subject: [PATCH] Start work on dragging tabs --- crates/gpui2/src/elements/div.rs | 3 +- crates/ui2/src/components/tab.rs | 52 +++++++++----------------------- crates/workspace2/src/pane.rs | 44 +++++++++++++++++++-------- 3 files changed, 48 insertions(+), 51 deletions(-) diff --git a/crates/gpui2/src/elements/div.rs b/crates/gpui2/src/elements/div.rs index bfa2e3ecdc..2438d26ed8 100644 --- a/crates/gpui2/src/elements/div.rs +++ b/crates/gpui2/src/elements/div.rs @@ -29,7 +29,7 @@ pub struct GroupStyle { pub style: Box, } -pub trait InteractiveElement: Sized + Element { +pub trait InteractiveElement: Sized { fn interactivity(&mut self) -> &mut Interactivity; fn group(mut self, group: impl Into) -> Self { @@ -436,7 +436,6 @@ pub trait StatefulInteractiveElement: InteractiveElement { "calling tooltip more than once on the same element is not supported" ); self.interactivity().tooltip_builder = Some(Rc::new(build_tooltip)); - self } } diff --git a/crates/ui2/src/components/tab.rs b/crates/ui2/src/components/tab.rs index 7a40a6ed0d..be1ce8dd12 100644 --- a/crates/ui2/src/components/tab.rs +++ b/crates/ui2/src/components/tab.rs @@ -1,10 +1,7 @@ -use std::cmp::Ordering; -use std::rc::Rc; - -use gpui::{AnyElement, AnyView, ClickEvent, IntoElement, MouseButton}; -use smallvec::SmallVec; - use crate::prelude::*; +use gpui::{AnyElement, IntoElement, Stateful}; +use smallvec::SmallVec; +use std::cmp::Ordering; /// The position of a [`Tab`] within a list of tabs. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -29,12 +26,10 @@ pub enum TabCloseSide { #[derive(IntoElement)] pub struct Tab { - id: ElementId, + div: Stateful
, selected: bool, position: TabPosition, close_side: TabCloseSide, - on_click: Option>, - tooltip: Option AnyView + 'static>>, start_slot: Option, end_slot: Option, children: SmallVec<[AnyElement; 2]>, @@ -43,12 +38,10 @@ pub struct Tab { impl Tab { pub fn new(id: impl Into) -> Self { Self { - id: id.into(), + div: div().id(id), selected: false, position: TabPosition::First, close_side: TabCloseSide::End, - on_click: None, - tooltip: None, start_slot: None, end_slot: None, children: SmallVec::new(), @@ -65,16 +58,6 @@ impl Tab { self } - pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self { - self.on_click = Some(Rc::new(handler)); - self - } - - pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self { - self.tooltip = Some(Box::new(tooltip)); - self - } - pub fn start_slot(mut self, element: impl Into>) -> Self { self.start_slot = element.into().map(IntoElement::into_any_element); self @@ -86,6 +69,14 @@ impl Tab { } } +impl InteractiveElement for Tab { + fn interactivity(&mut self) -> &mut gpui::Interactivity { + self.div.interactivity() + } +} + +impl StatefulInteractiveElement for Tab {} + impl Selectable for Tab { fn selected(mut self, selected: bool) -> Self { self.selected = selected; @@ -100,7 +91,7 @@ impl ParentElement for Tab { } impl RenderOnce for Tab { - type Rendered = Div; + type Rendered = Stateful
; fn render(self, cx: &mut WindowContext) -> Self::Rendered { const HEIGHT_IN_REMS: f32 = 30. / 16.; @@ -120,7 +111,7 @@ impl RenderOnce for Tab { ), }; - div() + self.div .h(rems(HEIGHT_IN_REMS)) .bg(tab_bg) .border_color(cx.theme().colors().border) @@ -146,7 +137,6 @@ impl RenderOnce for Tab { .child( h_stack() .group("") - .id(self.id) .relative() .h_full() .px_5() @@ -154,18 +144,6 @@ impl RenderOnce for Tab { .text_color(text_color) // .hover(|style| style.bg(tab_hover_bg)) // .active(|style| style.bg(tab_active_bg)) - .when_some(self.on_click, |tab, on_click| { - tab.cursor_pointer().on_click(move |event, cx| { - // HACK: GPUI currently fires `on_click` with any mouse button, - // but we only care about the left button. - if event.down.button == MouseButton::Left { - (on_click)(event, cx) - } - }) - }) - .when_some(self.tooltip, |tab, tooltip| { - tab.tooltip(move |cx| tooltip(cx)) - }) .child( h_stack() .w_3() diff --git a/crates/workspace2/src/pane.rs b/crates/workspace2/src/pane.rs index 9674e28263..d51f2067b9 100644 --- a/crates/workspace2/src/pane.rs +++ b/crates/workspace2/src/pane.rs @@ -7,10 +7,10 @@ use crate::{ use anyhow::Result; use collections::{HashMap, HashSet, VecDeque}; use gpui::{ - actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyWeakView, AppContext, - AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, Focusable, - FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, Render, - Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, + actions, impl_actions, overlay, prelude::*, Action, AnchorCorner, AnyDrag, AnyWeakView, + AppContext, AsyncWindowContext, DismissEvent, Div, EntityId, EventEmitter, FocusHandle, + Focusable, FocusableView, Model, MouseButton, NavigationDirection, Pixels, Point, PromptLevel, + Render, Subscription, Task, View, ViewContext, VisualContext, WeakView, WindowContext, }; use parking_lot::Mutex; use project::{Project, ProjectEntryId, ProjectPath}; @@ -25,6 +25,7 @@ use std::{ Arc, }, }; +use theme::ThemeSettings; use ui::{ h_stack, prelude::*, right_click_menu, ButtonSize, Color, Icon, IconButton, IconSize, @@ -231,6 +232,13 @@ pub struct NavigationEntry { pub timestamp: usize, } +struct DraggedTab { + pub pane: View, + pub ix: usize, + pub detail: usize, + pub is_active: bool, +} + // pub struct DraggedItem { // pub handle: Box, // pub pane: WeakView, @@ -1501,7 +1509,17 @@ impl Pane { .on_click(cx.listener(move |pane: &mut Self, event, cx| { pane.activate_item(ix, true, true, cx) })) - // .on_drag(move |pane, cx| pane.render_tab(ix, item.boxed_clone(), detail, cx)) + .on_drag({ + let pane = cx.view().clone(); + move |cx| { + cx.build_view(|cx| DraggedTab { + pane: pane.clone(), + detail, + is_active, + ix, + }) + } + }) // .drag_over::(|d| d.bg(cx.theme().colors().element_drop_target)) // .on_drop(|_view, state: View, cx| { // eprintln!("{:?}", state.read(cx)); @@ -3131,15 +3149,17 @@ fn dirty_message_for(buffer_path: Option) -> String { // } // } -#[derive(Clone, Debug)] -struct DraggedTab { - title: String, -} - impl Render for DraggedTab { - type Element = Div; + type Element = ::Rendered; fn render(&mut self, cx: &mut ViewContext) -> Self::Element { - div().w_8().h_4().bg(gpui::red()) + let ui_font = ThemeSettings::get_global(cx).ui_font.family.clone(); + let item = &self.pane.read(cx).items[self.ix]; + let label = item.tab_content(Some(self.detail), false, cx); + Tab::new("") + .selected(self.is_active) + .child(label) + .render(cx) + .font(ui_font) } }