@@ -1,8 +1,9 @@
use crate::{status_bar::StatusItemView, Workspace};
+use crate::{DockClickReset, DockDragState};
use gpui::{
- div, px, Action, AnchorCorner, AnyView, AppContext, Axis, Div, Entity, EntityId, EventEmitter,
- FocusHandle, FocusableView, IntoElement, ParentElement, Render, SharedString, Styled,
- Subscription, View, ViewContext, VisualContext, WeakView, WindowContext,
+ div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Div, Entity, EntityId,
+ EventEmitter, FocusHandle, FocusableView, IntoElement, MouseButton, ParentElement, Render,
+ SharedString, Styled, Subscription, View, ViewContext, VisualContext, WeakView, WindowContext,
};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@@ -364,7 +365,7 @@ impl Dock {
this.set_open(false, cx);
}
}
- PanelEvent::Focus => todo!(),
+ PanelEvent::Focus => {}
}),
];
@@ -485,6 +486,48 @@ impl Render for Dock {
if let Some(entry) = self.visible_entry() {
let size = entry.panel.size(cx);
+ let mut pre_resize_handle = None;
+ let mut post_resize_handle = None;
+ let position = self.position;
+ let handler = div()
+ .id("resize-handle")
+ .bg(gpui::red())
+ .on_mouse_down(gpui::MouseButton::Left, move |_, cx| {
+ cx.update_global(|drag: &mut DockDragState, cx| drag.0 = Some(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();
+ }));
+ }
+ })
+ }
+ }));
+
+ match self.position() {
+ DockPosition::Left => {
+ post_resize_handle = Some(handler.w_2().h_full().cursor_col_resize())
+ }
+ DockPosition::Bottom => {
+ pre_resize_handle = Some(handler.w_full().h_2().cursor_row_resize())
+ }
+ DockPosition::Right => {
+ pre_resize_handle = Some(handler.w_full().h_1().cursor_col_resize())
+ }
+ }
+
div()
.border_color(cx.theme().colors().border)
.map(|this| match self.position().axis() {
@@ -496,7 +539,9 @@ impl Render for Dock {
DockPosition::Right => this.border_l(),
DockPosition::Bottom => this.border_t(),
})
+ .children(pre_resize_handle)
.child(entry.panel.to_any())
+ .children(post_resize_handle)
} else {
div()
}
@@ -29,12 +29,12 @@ use futures::{
Future, FutureExt, StreamExt,
};
use gpui::{
- actions, div, impl_actions, point, size, Action, AnyModel, AnyView, AnyWeakView,
+ 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, ParentElement, PathPromptOptions, Point,
- PromptLevel, Render, Size, Styled, Subscription, Task, View, ViewContext, VisualContext,
- WeakView, WindowBounds, WindowContext, WindowHandle, WindowOptions,
+ KeyContext, ManagedView, Model, ModelContext, MouseMoveEvent, 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,6 +227,9 @@ 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);
@@ -480,8 +483,6 @@ struct FollowerState {
items_by_leader_view_id: HashMap<ViewId, Box<dyn FollowableItemHandle>>,
}
-enum WorkspaceBounds {}
-
impl Workspace {
pub fn new(
workspace_id: WorkspaceId,
@@ -3571,6 +3572,16 @@ 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<()>>);
+
impl Render for Workspace {
type Element = Div;
@@ -3614,6 +3625,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 {
+ DockPosition::Left => {
+ let size = e.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;
+ 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;
+ 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()