Merge remote-tracking branch 'origin/main' into perf-2
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::DraggedDock;
|
||||
use crate::{status_bar::StatusItemView, Workspace};
|
||||
use crate::{DockClickReset, DockDragState};
|
||||
use gpui::{
|
||||
div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Div, Entity, EntityId,
|
||||
EventEmitter, FocusHandle, FocusableView, IntoElement, MouseButton, ParentElement, Render,
|
||||
@@ -493,47 +493,37 @@ impl Render for Dock {
|
||||
let handler = div()
|
||||
.id("resize-handle")
|
||||
.bg(cx.theme().colors().border)
|
||||
.on_mouse_down(gpui::MouseButton::Left, move |_, cx| {
|
||||
cx.update_global(|drag: &mut DockDragState, cx| drag.0 = Some(position))
|
||||
})
|
||||
.on_drag(move |cx| cx.build_view(|_| DraggedDock(position)))
|
||||
.on_click(cx.listener(|v, e: &ClickEvent, cx| {
|
||||
if e.down.button == MouseButton::Left {
|
||||
cx.update_global(|state: &mut DockClickReset, cx| {
|
||||
if state.0.is_some() {
|
||||
state.0 = None;
|
||||
v.resize_active_panel(None, cx)
|
||||
} else {
|
||||
let double_click = cx.double_click_interval();
|
||||
let timer = cx.background_executor().timer(double_click);
|
||||
state.0 = Some(cx.spawn(|_, mut cx| async move {
|
||||
timer.await;
|
||||
cx.update_global(|state: &mut DockClickReset, cx| {
|
||||
state.0 = None;
|
||||
})
|
||||
.ok();
|
||||
}));
|
||||
}
|
||||
})
|
||||
if e.down.button == MouseButton::Left && e.down.click_count == 2 {
|
||||
v.resize_active_panel(None, cx)
|
||||
}
|
||||
}));
|
||||
}))
|
||||
.z_index(1);
|
||||
|
||||
const HANDLE_SIZE: Pixels = Pixels(6.);
|
||||
|
||||
match self.position() {
|
||||
DockPosition::Left => {
|
||||
post_resize_handle = Some(handler.w_1().h_full().cursor_col_resize())
|
||||
post_resize_handle =
|
||||
Some(handler.min_w(HANDLE_SIZE).h_full().cursor_col_resize())
|
||||
}
|
||||
DockPosition::Bottom => {
|
||||
pre_resize_handle = Some(handler.w_full().h_1().cursor_row_resize())
|
||||
pre_resize_handle =
|
||||
Some(handler.w_full().min_h(HANDLE_SIZE).cursor_row_resize())
|
||||
}
|
||||
DockPosition::Right => {
|
||||
pre_resize_handle = Some(handler.w_full().h_1().cursor_col_resize())
|
||||
pre_resize_handle =
|
||||
Some(handler.min_w(HANDLE_SIZE).h_full().cursor_col_resize())
|
||||
}
|
||||
}
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.map(|this| match self.position().axis() {
|
||||
Axis::Horizontal => this.w(px(size)).h_full(),
|
||||
Axis::Vertical => this.h(px(size)).w_full(),
|
||||
Axis::Horizontal => this.w(px(size)).h_full().flex_row(),
|
||||
Axis::Vertical => this.h(px(size)).w_full().flex_col(),
|
||||
})
|
||||
.map(|this| match self.position() {
|
||||
DockPosition::Left => this.border_r(),
|
||||
@@ -541,7 +531,14 @@ impl Render for Dock {
|
||||
DockPosition::Bottom => this.border_t(),
|
||||
})
|
||||
.children(pre_resize_handle)
|
||||
.child(entry.panel.to_any())
|
||||
.child(
|
||||
div()
|
||||
.map(|this| match self.position().axis() {
|
||||
Axis::Horizontal => this.min_w(px(size) - HANDLE_SIZE).h_full(),
|
||||
Axis::Vertical => this.min_h(px(size) - HANDLE_SIZE).w_full(),
|
||||
})
|
||||
.child(entry.panel.to_any()),
|
||||
)
|
||||
.children(post_resize_handle)
|
||||
} else {
|
||||
div()
|
||||
|
||||
@@ -1759,6 +1759,34 @@ impl Pane {
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
|
||||
fn handle_split_tab_drop(
|
||||
&mut self,
|
||||
dragged_tab: &View<DraggedTab>,
|
||||
split_direction: SplitDirection,
|
||||
cx: &mut ViewContext<'_, Pane>,
|
||||
) {
|
||||
let dragged_tab = dragged_tab.read(cx);
|
||||
let item_id = dragged_tab.item_id;
|
||||
let from_pane = dragged_tab.pane.clone();
|
||||
let to_pane = cx.view().clone();
|
||||
self.workspace
|
||||
.update(cx, |workspace, cx| {
|
||||
cx.defer(move |workspace, cx| {
|
||||
let item = from_pane
|
||||
.read(cx)
|
||||
.items()
|
||||
.find(|item| item.item_id() == item_id)
|
||||
.map(|item| item.boxed_clone());
|
||||
if let Some(item) = item {
|
||||
if let Some(item) = item.clone_on_split(workspace.database_id(), cx) {
|
||||
workspace.split_item(split_direction, item, cx);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
.log_err();
|
||||
}
|
||||
}
|
||||
|
||||
impl FocusableView for Pane {
|
||||
@@ -1852,7 +1880,54 @@ impl Render for Pane {
|
||||
.child(self.render_tab_bar(cx))
|
||||
.child(self.toolbar.clone())
|
||||
.child(if let Some(item) = self.active_item() {
|
||||
div().flex().flex_1().child(item.to_any())
|
||||
let mut drag_target_color = cx.theme().colors().text;
|
||||
drag_target_color.a = 0.5;
|
||||
|
||||
div()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.relative()
|
||||
.child(item.to_any())
|
||||
.child(
|
||||
div()
|
||||
.absolute()
|
||||
.full()
|
||||
.z_index(1)
|
||||
.drag_over::<DraggedTab>(|style| style.bg(drag_target_color))
|
||||
.on_drop(cx.listener(
|
||||
move |this, dragged_tab: &View<DraggedTab>, cx| {
|
||||
this.handle_tab_drop(dragged_tab, this.active_item_index(), cx)
|
||||
},
|
||||
)),
|
||||
)
|
||||
.children(
|
||||
[
|
||||
(SplitDirection::Up, 2),
|
||||
(SplitDirection::Down, 2),
|
||||
(SplitDirection::Left, 3),
|
||||
(SplitDirection::Right, 3),
|
||||
]
|
||||
.into_iter()
|
||||
.map(|(direction, z_index)| {
|
||||
let div = div()
|
||||
.absolute()
|
||||
.z_index(z_index)
|
||||
.invisible()
|
||||
.bg(drag_target_color)
|
||||
.drag_over::<DraggedTab>(|style| style.visible())
|
||||
.on_drop(cx.listener(
|
||||
move |this, dragged_tab: &View<DraggedTab>, cx| {
|
||||
this.handle_split_tab_drop(dragged_tab, direction, cx)
|
||||
},
|
||||
));
|
||||
match direction {
|
||||
SplitDirection::Up => div.top_0().left_0().right_0().h_32(),
|
||||
SplitDirection::Down => div.left_0().bottom_0().right_0().h_32(),
|
||||
SplitDirection::Left => div.top_0().left_0().bottom_0().w_32(),
|
||||
SplitDirection::Right => div.top_0().bottom_0().right_0().w_32(),
|
||||
}
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
h_stack()
|
||||
.items_center()
|
||||
|
||||
@@ -55,6 +55,12 @@ pub struct Toolbar {
|
||||
}
|
||||
|
||||
impl Toolbar {
|
||||
fn has_any_visible_items(&self) -> bool {
|
||||
self.items
|
||||
.iter()
|
||||
.any(|(_item, location)| *location != ToolbarItemLocation::Hidden)
|
||||
}
|
||||
|
||||
fn left_items(&self) -> impl Iterator<Item = &dyn ToolbarItemViewHandle> {
|
||||
self.items.iter().filter_map(|(item, location)| {
|
||||
if *location == ToolbarItemLocation::PrimaryLeft {
|
||||
@@ -74,12 +80,28 @@ impl Toolbar {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn secondary_items(&self) -> impl Iterator<Item = &dyn ToolbarItemViewHandle> {
|
||||
self.items.iter().filter_map(|(item, location)| {
|
||||
if *location == ToolbarItemLocation::Secondary {
|
||||
Some(item.as_ref())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Toolbar {
|
||||
type Element = Div;
|
||||
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||
if !self.has_any_visible_items() {
|
||||
return div();
|
||||
}
|
||||
|
||||
let secondary_item = self.secondary_items().next().map(|item| item.to_any());
|
||||
|
||||
v_stack()
|
||||
.border_b()
|
||||
.border_color(cx.theme().colors().border_variant)
|
||||
@@ -87,8 +109,10 @@ impl Render for Toolbar {
|
||||
.child(
|
||||
h_stack()
|
||||
.justify_between()
|
||||
.children(self.items.iter().map(|(child, _)| child.to_any())),
|
||||
.child(h_stack().children(self.left_items().map(|item| item.to_any())))
|
||||
.child(h_stack().children(self.right_items().map(|item| item.to_any()))),
|
||||
)
|
||||
.children(secondary_item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,11 +30,11 @@ use futures::{
|
||||
};
|
||||
use gpui::{
|
||||
actions, canvas, div, impl_actions, point, size, Action, AnyModel, AnyView, AnyWeakView,
|
||||
AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div, Entity,
|
||||
EntityId, EventEmitter, FocusHandle, FocusableView, GlobalPixels, InteractiveElement,
|
||||
KeyContext, ManagedView, Model, ModelContext, MouseMoveEvent, ParentElement, PathPromptOptions,
|
||||
Pixels, Point, PromptLevel, Render, Size, Styled, Subscription, Task, View, ViewContext,
|
||||
VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
AnyWindowHandle, AppContext, AsyncAppContext, AsyncWindowContext, Bounds, Context, Div,
|
||||
DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle, FocusableView, GlobalPixels,
|
||||
InteractiveElement, KeyContext, ManagedView, Model, ModelContext, ParentElement,
|
||||
PathPromptOptions, Pixels, Point, PromptLevel, Render, Size, Styled, Subscription, Task, View,
|
||||
ViewContext, VisualContext, WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
|
||||
};
|
||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ItemSettings, ProjectItem};
|
||||
use itertools::Itertools;
|
||||
@@ -227,9 +227,6 @@ pub fn init_settings(cx: &mut AppContext) {
|
||||
}
|
||||
|
||||
pub fn init(app_state: Arc<AppState>, cx: &mut AppContext) {
|
||||
cx.default_global::<DockDragState>();
|
||||
cx.default_global::<DockClickReset>();
|
||||
|
||||
init_settings(cx);
|
||||
notifications::init(cx);
|
||||
|
||||
@@ -466,6 +463,7 @@ pub struct Workspace {
|
||||
_observe_current_user: Task<Result<()>>,
|
||||
_schedule_serialize: Option<Task<()>>,
|
||||
pane_history_timestamp: Arc<AtomicUsize>,
|
||||
bounds: Bounds<Pixels>,
|
||||
}
|
||||
|
||||
impl EventEmitter<Event> for Workspace {}
|
||||
@@ -708,6 +706,8 @@ impl Workspace {
|
||||
subscriptions,
|
||||
pane_history_timestamp,
|
||||
workspace_actions: Default::default(),
|
||||
// This data will be incorrect, but it will be overwritten by the time it needs to be used.
|
||||
bounds: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1145,7 +1145,7 @@ impl Workspace {
|
||||
let window = cx.window_handle();
|
||||
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
let workspace_count = cx.update(|_, cx| {
|
||||
let workspace_count = (*cx).update(|cx| {
|
||||
cx.windows()
|
||||
.iter()
|
||||
.filter(|window| window.downcast::<Workspace>().is_some())
|
||||
@@ -3580,13 +3580,8 @@ impl FocusableView for Workspace {
|
||||
|
||||
struct WorkspaceBounds(Bounds<Pixels>);
|
||||
|
||||
//todo!("remove this when better drag APIs are in GPUI2")
|
||||
#[derive(Default)]
|
||||
struct DockDragState(Option<DockPosition>);
|
||||
|
||||
//todo!("remove this when better double APIs are in GPUI2")
|
||||
#[derive(Default)]
|
||||
struct DockClickReset(Option<Task<()>>);
|
||||
#[derive(Render)]
|
||||
struct DraggedDock(DockPosition);
|
||||
|
||||
impl Render for Workspace {
|
||||
type Element = Div;
|
||||
@@ -3632,37 +3627,37 @@ impl Render for Workspace {
|
||||
.border_t()
|
||||
.border_b()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.on_mouse_up(gpui::MouseButton::Left, |_, cx| {
|
||||
cx.update_global(|drag: &mut DockDragState, cx| {
|
||||
drag.0 = None;
|
||||
})
|
||||
})
|
||||
.on_mouse_move(cx.listener(|workspace, e: &MouseMoveEvent, cx| {
|
||||
if let Some(types) = &cx.global::<DockDragState>().0 {
|
||||
let workspace_bounds = cx.global::<WorkspaceBounds>().0;
|
||||
match types {
|
||||
.child(
|
||||
canvas(cx.listener(|workspace, bounds, cx| {
|
||||
workspace.bounds = *bounds;
|
||||
}))
|
||||
.absolute()
|
||||
.size_full(),
|
||||
)
|
||||
.on_drag_move(
|
||||
cx.listener(|workspace, e: &DragMoveEvent<DraggedDock>, cx| {
|
||||
match e.drag.read(cx).0 {
|
||||
DockPosition::Left => {
|
||||
let size = e.position.x;
|
||||
let size = workspace.bounds.left() + e.event.position.x;
|
||||
workspace.left_dock.update(cx, |left_dock, cx| {
|
||||
left_dock.resize_active_panel(Some(size.0), cx);
|
||||
});
|
||||
}
|
||||
DockPosition::Right => {
|
||||
let size = workspace_bounds.size.width - e.position.x;
|
||||
let size = workspace.bounds.right() - e.event.position.x;
|
||||
workspace.right_dock.update(cx, |right_dock, cx| {
|
||||
right_dock.resize_active_panel(Some(size.0), cx);
|
||||
});
|
||||
}
|
||||
DockPosition::Bottom => {
|
||||
let size = workspace_bounds.size.height - e.position.y;
|
||||
let size = workspace.bounds.bottom() - e.event.position.y;
|
||||
workspace.bottom_dock.update(cx, |bottom_dock, cx| {
|
||||
bottom_dock.resize_active_panel(Some(size.0), cx);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
.child(canvas(|bounds, cx| cx.set_global(WorkspaceBounds(bounds))))
|
||||
}),
|
||||
)
|
||||
.child(self.modal_layer.clone())
|
||||
.child(
|
||||
div()
|
||||
|
||||
Reference in New Issue
Block a user