@@ -7,7 +7,7 @@ use client::proto;
use gpui::{
Action, AnyElement, AnyView, App, Axis, Context, Corner, Entity, EntityId, EventEmitter,
FocusHandle, Focusable, IntoElement, KeyContext, MouseButton, MouseDownEvent, MouseUpEvent,
- ParentElement, Render, SharedString, StyleRefinement, Styled, Subscription, WeakEntity, Window,
+ ParentElement, Render, SharedString, Styled, Subscription, WeakEntity, Window,
deferred, div, px,
};
use settings::SettingsStore;
@@ -257,6 +257,12 @@ pub enum DockPosition {
Right,
}
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum DockPart {
+ Fixed,
+ Flexible,
+}
+
impl From<settings::DockPosition> for DockPosition {
fn from(value: settings::DockPosition) -> Self {
match value {
@@ -392,7 +398,7 @@ impl Dock {
self.is_open
}
- fn resizable(&self, cx: &App) -> bool {
+ pub fn resizable(&self, cx: &App) -> bool {
!(self.zoom_layer_open || self.modal_layer.read(cx).has_active_modal())
}
@@ -797,10 +803,9 @@ impl Dock {
}
}
- fn dispatch_context() -> KeyContext {
+ pub fn dispatch_context() -> KeyContext {
let mut dispatch_context = KeyContext::new_with_defaults();
dispatch_context.add("Dock");
-
dispatch_context
}
@@ -814,110 +819,68 @@ impl Dock {
}
}
-impl Render for Dock {
- fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
- let dispatch_context = Self::dispatch_context();
- if let Some(entry) = self
- .visible_entry()
- .filter(|entry| entry.panel.has_panel_content(window, cx))
- {
- let size = entry.panel.size(window, cx);
-
- let panel_content = entry
- .panel
- .to_any()
- .cached(StyleRefinement::default().v_flex().size_full());
-
- let position = self.position;
- let create_resize_handle = || {
- let handle = div()
- .id("resize-handle")
- .on_drag(DraggedDock { position }, |dock, _, _, cx| {
- cx.stop_propagation();
- cx.new(|_| dock.clone())
- })
- .on_mouse_down(
- MouseButton::Left,
- cx.listener(|_, _: &MouseDownEvent, _, cx| {
- cx.stop_propagation();
- }),
- )
- .on_mouse_up(
- MouseButton::Left,
- cx.listener(|dock, e: &MouseUpEvent, window, cx| {
- if e.click_count == 2 {
- dock.resize_active_panel(None, window, cx);
- dock.workspace
- .update(cx, |workspace, cx| {
- workspace.serialize_workspace(window, cx);
- })
- .ok();
- cx.stop_propagation();
- }
- }),
- )
- .occlude();
- match self.position() {
- DockPosition::Left => deferred(
- handle
- .absolute()
- .right(-RESIZE_HANDLE_SIZE / 2.)
- .top(px(0.))
- .h_full()
- .w(RESIZE_HANDLE_SIZE)
- .cursor_col_resize(),
- ),
- DockPosition::Bottom => deferred(
- handle
- .absolute()
- .top(-RESIZE_HANDLE_SIZE / 2.)
- .left(px(0.))
- .w_full()
- .h(RESIZE_HANDLE_SIZE)
- .cursor_row_resize(),
- ),
- DockPosition::Right => deferred(
- handle
- .absolute()
- .top(px(0.))
- .left(-RESIZE_HANDLE_SIZE / 2.)
- .h_full()
- .w(RESIZE_HANDLE_SIZE)
- .cursor_col_resize(),
- ),
+pub fn create_resize_handle(
+ position: DockPosition,
+ part: DockPart,
+ cx: &mut Context<Workspace>,
+) -> gpui::Deferred {
+ let handle = div()
+ .id(match part {
+ DockPart::Fixed => "resize-handle",
+ DockPart::Flexible => "flexible-resize-handle",
+ })
+ .on_drag(DraggedDock { position, part }, |dock, _, _, cx| {
+ cx.stop_propagation();
+ cx.new(|_| dock.clone())
+ })
+ .on_mouse_down(
+ MouseButton::Left,
+ cx.listener(|_, _: &MouseDownEvent, _, cx| {
+ cx.stop_propagation();
+ }),
+ )
+ .on_mouse_up(
+ MouseButton::Left,
+ cx.listener(move |workspace, e: &MouseUpEvent, window, cx| {
+ if e.click_count == 2 {
+ let dock = workspace.dock_at_position(position);
+ dock.update(cx, |dock, cx| {
+ dock.resize_active_panel(None, window, cx);
+ });
+ workspace.serialize_workspace(window, cx);
+ cx.stop_propagation();
}
- };
-
- div()
- .key_context(dispatch_context)
- .track_focus(&self.focus_handle(cx))
- .flex()
- .bg(cx.theme().colors().panel_background)
- .border_color(cx.theme().colors().border)
- .overflow_hidden()
- .map(|this| match self.position().axis() {
- Axis::Horizontal => this
- .h_full()
- .flex_row()
- .child(div().w(size).h_full().child(panel_content)),
- Axis::Vertical => this
- .w_full()
- .flex_col()
- .child(div().h(size).w_full().child(panel_content)),
- })
- .map(|this| match self.position() {
- DockPosition::Left => this.border_r_1(),
- DockPosition::Right => this.border_l_1(),
- DockPosition::Bottom => this.border_t_1(),
- })
- .when(self.resizable(cx), |this| {
- this.child(create_resize_handle())
- })
- } else {
- div()
- .key_context(dispatch_context)
- .track_focus(&self.focus_handle(cx))
- }
+ }),
+ )
+ .occlude();
+ match position {
+ DockPosition::Left => deferred(
+ handle
+ .absolute()
+ .right(-RESIZE_HANDLE_SIZE / 2.)
+ .top(px(0.))
+ .h_full()
+ .w(RESIZE_HANDLE_SIZE)
+ .cursor_col_resize(),
+ ),
+ DockPosition::Bottom => deferred(
+ handle
+ .absolute()
+ .top(-RESIZE_HANDLE_SIZE / 2.)
+ .left(px(0.))
+ .w_full()
+ .h(RESIZE_HANDLE_SIZE)
+ .cursor_row_resize(),
+ ),
+ DockPosition::Right => deferred(
+ handle
+ .absolute()
+ .top(px(0.))
+ .left(-RESIZE_HANDLE_SIZE / 2.)
+ .h_full()
+ .w(RESIZE_HANDLE_SIZE)
+ .cursor_col_resize(),
+ ),
}
}
@@ -51,12 +51,13 @@ use futures::{
future::{Shared, try_join_all},
};
use gpui::{
- Action, AnyElement, AnyEntity, AnyView, AnyWeakView, App, AsyncApp, AsyncWindowContext, Bounds,
- Context, CursorStyle, Decorations, DragMoveEvent, Entity, EntityId, EventEmitter, FocusHandle,
- Focusable, Global, HitboxBehavior, Hsla, KeyContext, Keystroke, ManagedView, MouseButton,
- PathPromptOptions, Point, PromptLevel, Render, ResizeEdge, Size, Stateful, Subscription,
- SystemWindowTabController, Task, Tiling, WeakEntity, WindowBounds, WindowHandle, WindowId,
- WindowOptions, actions, canvas, point, relative, size, transparent_black,
+ Action, AnyElement, AnyEntity, AnyView, AnyWeakView, App, AsyncApp, AsyncWindowContext, Axis,
+ Bounds, Context, CursorStyle, Decorations, DragMoveEvent, Entity, EntityId, EventEmitter,
+ FocusHandle, Focusable, Global, HitboxBehavior, Hsla, KeyContext, Keystroke, ManagedView,
+ MouseButton, PathPromptOptions, Point, PromptLevel, Render, ResizeEdge, Size, Stateful,
+ StyleRefinement, Subscription, SystemWindowTabController, Task, Tiling, WeakEntity,
+ WindowBounds, WindowHandle, WindowId, WindowOptions, actions, canvas, point, relative, size,
+ transparent_black,
};
pub use history_manager::*;
pub use item::{
@@ -148,7 +149,7 @@ pub use workspace_settings::{
};
use zed_actions::{Spawn, feedback::FileBugReport};
-use crate::{item::ItemBufferKind, notifications::NotificationId};
+use crate::{dock::DockPart, item::ItemBufferKind, notifications::NotificationId};
use crate::{
persistence::{
SerializedAxis,
@@ -6973,7 +6974,7 @@ impl Workspace {
position: DockPosition,
dock: &Entity<Dock>,
window: &mut Window,
- cx: &mut App,
+ cx: &mut Context<Self>,
) -> impl Iterator<Item = AnyElement> {
let mut results = [None, None];
@@ -6987,12 +6988,57 @@ impl Workspace {
leader_border_for_pane(follower_states, &pane, window, cx)
});
+ let fixed_content = {
+ let dispatch_context = Dock::dispatch_context();
+ if let Some(panel) = dock
+ .read(cx)
+ .visible_panel()
+ .filter(|panel| panel.has_panel_content(window, cx))
+ {
+ let size = panel.size(window, cx);
+
+ let panel_content = panel
+ .to_any()
+ .cached(StyleRefinement::default().v_flex().size_full());
+
+ div()
+ .key_context(dispatch_context)
+ .track_focus(&self.focus_handle(cx))
+ .flex()
+ .bg(cx.theme().colors().panel_background)
+ .border_color(cx.theme().colors().border)
+ .overflow_hidden()
+ .map(|this| match position.axis() {
+ Axis::Horizontal => this
+ .h_full()
+ .flex_row()
+ .child(div().w(size).h_full().child(panel_content)),
+ Axis::Vertical => this
+ .w_full()
+ .flex_col()
+ .child(div().h(size).w_full().child(panel_content)),
+ })
+ .map(|this| match position {
+ DockPosition::Left => this.border_r_1(),
+ DockPosition::Right => this.border_l_1(),
+ DockPosition::Bottom => this.border_t_1(),
+ })
+ .when(dock.read(cx).resizable(cx), |this| {
+ this.child(dock::create_resize_handle(position, DockPart::Fixed, cx))
+ })
+ } else {
+ div()
+ .key_context(dispatch_context)
+ .track_focus(&self.focus_handle(cx))
+ }
+ };
+
results[0] = Some(
div()
.flex()
.flex_none()
.overflow_hidden()
- .child(dock.clone())
+ .child(fixed_content)
.children(leader_border)
.into_any_element(),
);
@@ -7008,7 +7054,13 @@ impl Workspace {
.flex_1()
.min_w(px(10.))
.flex_grow()
+ .when(position == DockPosition::Right, |this| {
+ this.child(dock::create_resize_handle(position, DockPart::Flexible, cx))
+ })
.child(flex_content)
+ .when(position == DockPosition::Left, |this| {
+ this.child(dock::create_resize_handle(position, DockPart::Flexible, cx))
+ })
.into_any_element()
});
@@ -7246,6 +7298,11 @@ impl Workspace {
}
}
+fn render_resize_handle() -> impl IntoElement {
+ // FIXME: actually render the handle and wire it up.
+ div().debug_bg_magenta()
+}
+
pub trait AnyActiveCall {
fn entity(&self) -> AnyEntity;
fn is_in_room(&self, _: &App) -> bool;
@@ -7590,6 +7647,7 @@ impl Focusable for Workspace {
#[derive(Clone)]
struct DraggedDock {
position: DockPosition,
+ part: DockPart,
}
impl Render for DraggedDock {
@@ -7723,39 +7781,74 @@ impl Render for Workspace {
.when(self.zoomed.is_none(), |this| {
this.on_drag_move(cx.listener(
move |workspace, e: &DragMoveEvent<DraggedDock>, window, cx| {
- if workspace.previous_dock_drag_coordinates
- != Some(e.event.position)
- {
- workspace.previous_dock_drag_coordinates =
- Some(e.event.position);
-
- match e.drag(cx).position {
- DockPosition::Left => {
- workspace.resize_left_dock(
- e.event.position.x
- - workspace.bounds.left(),
- window,
- cx,
- );
+ let drag = e.drag(cx);
+ match drag.part {
+ DockPart::Fixed => {
+ if workspace.previous_dock_drag_coordinates
+ != Some(e.event.position)
+ {
+ workspace.previous_dock_drag_coordinates =
+ Some(e.event.position);
+
+ match e.drag(cx).position {
+ DockPosition::Left => {
+ workspace.resize_left_dock(
+ e.event.position.x
+ - workspace.bounds.left(),
+ window,
+ cx,
+ );
+ }
+ DockPosition::Right => {
+ workspace.resize_right_dock(
+ workspace.bounds.right()
+ - e.event.position.x,
+ window,
+ cx,
+ );
+ }
+ DockPosition::Bottom => {
+ workspace.resize_bottom_dock(
+ workspace.bounds.bottom()
+ - e.event.position.y,
+ window,
+ cx,
+ );
+ }
+ };
+ workspace.serialize_workspace(window, cx);
}
- DockPosition::Right => {
- workspace.resize_right_dock(
- workspace.bounds.right()
- - e.event.position.x,
- window,
- cx,
- );
- }
- DockPosition::Bottom => {
- workspace.resize_bottom_dock(
- workspace.bounds.bottom()
- - e.event.position.y,
- window,
- cx,
- );
+ }
+ DockPart::Flexible => {
+ match drag.position {
+ DockPosition::Left => {
+ let fixed_width = workspace
+ .left_dock
+ .read(cx)
+ .active_panel()
+ .map_or(px(0.0), |p| {
+ p.size(window, cx)
+ });
+ let start_x =
+ workspace.bounds.left() + fixed_width;
+ let new_width =
+ e.event.position.x - start_x;
+
+ dbg!(&e.event.position);
+ dbg!(&workspace.bounds);
+ dbg!(&fixed_width);
+ dbg!(&start_x);
+ dbg!(new_width);
+ //
+ }
+ DockPosition::Right => {
+ //
+ }
+ DockPosition::Bottom => unreachable!(
+ "bottom dock cannot have flex content"
+ ),
}
- };
- workspace.serialize_workspace(window, cx);
+ }
}
},
))