dock: Improve dock, panel to support absolute or fraction size. (#839)

This commit is contained in:
Jason Lee 2025-05-08 12:01:16 +08:00 committed by GitHub
parent 4aaaaa2d91
commit a26311dc0e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 56 additions and 27 deletions

View file

@ -279,7 +279,7 @@ impl StoryWorkspace {
cx,
),
],
vec![None, Some(0.2)],
vec![None, Some(relative(0.2))],
&dock_area,
window,
cx,
@ -328,9 +328,9 @@ impl StoryWorkspace {
_ = dock_area.update(cx, |view, cx| {
view.set_version(MAIN_DOCK_AREA.version, window, cx);
view.set_center(dock_item, window, cx);
view.set_left_dock(left_panels, 0.3, true, window, cx);
view.set_bottom_dock(bottom_panels, 0.2, true, window, cx);
view.set_right_dock(right_panels, 0.3, true, window, cx);
view.set_left_dock(left_panels, relative(0.3), true, window, cx);
view.set_bottom_dock(bottom_panels, relative(0.2), true, window, cx);
view.set_right_dock(right_panels, px(320.), true, window, cx);
Self::save_state(&view.dump(cx)).unwrap();
});

View file

@ -3,9 +3,9 @@
use std::{ops::Deref, sync::Arc};
use gpui::{
div, prelude::FluentBuilder as _, px, Along, App, AppContext, Axis, Context, Element, Empty,
Entity, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels, Point, Render,
Style, StyleRefinement, Styled as _, WeakEntity, Window,
div, prelude::FluentBuilder as _, px, Along, App, AppContext, Axis, Context, DefiniteLength,
Element, Empty, Entity, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels,
Point, Render, Style, StyleRefinement, Styled as _, WeakEntity, Window,
};
use serde::{Deserialize, Serialize};
@ -14,7 +14,7 @@ use crate::{
StyledExt,
};
use super::{DockArea, DockItem, PanelView, TabPanel};
use super::{definite_length_to_window_ratio, DockArea, DockItem, PanelView, TabPanel};
#[derive(Clone)]
struct ResizePanel;
@ -249,8 +249,13 @@ impl Dock {
}
/// Set the size of the Dock.
pub fn set_ratio(&mut self, ratio: f32, _: &mut Window, cx: &mut Context<Self>) {
self.ratio = ratio;
pub fn set_size(
&mut self,
size: impl Into<DefiniteLength>,
window: &mut Window,
cx: &mut Context<Self>,
) {
self.ratio = definite_length_to_window_ratio(size, self.placement.axis(), window);
cx.notify();
}

View file

@ -8,9 +8,10 @@ mod tiles;
use anyhow::Result;
use gpui::{
actions, canvas, div, prelude::FluentBuilder, AnyElement, AnyView, App, AppContext, Axis,
Bounds, Context, Edges, Entity, EntityId, EventEmitter, InteractiveElement as _, IntoElement,
ParentElement as _, Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window,
actions, canvas, div, prelude::FluentBuilder, relative, Along, AnyElement, AnyView, App,
AppContext, Axis, Bounds, Context, DefiniteLength, Edges, Entity, EntityId, EventEmitter,
InteractiveElement as _, IntoElement, ParentElement as _, Pixels, Render, SharedString, Styled,
Subscription, WeakEntity, Window,
};
use std::sync::Arc;
@ -27,6 +28,22 @@ pub fn init(cx: &mut App) {
actions!(dock, [ToggleZoom, ClosePanel]);
/// Convert [`gpui::DefiniteLength`] to ratio of window.
pub(crate) fn definite_length_to_window_ratio(
length: impl Into<DefiniteLength>,
axis: Axis,
window: &Window,
) -> f32 {
let length: DefiniteLength = length.into();
match length {
DefiniteLength::Absolute(size) => {
let container_size = window.bounds().size.along(axis);
size.to_pixels(window.rem_size()) / container_size
}
DefiniteLength::Fraction(ratio) => ratio,
}
}
pub enum DockEvent {
/// The layout of the dock has changed, subscribers this to save the layout.
///
@ -143,12 +160,17 @@ impl DockItem {
pub fn split_with_sizes(
axis: Axis,
items: Vec<DockItem>,
ratios: Vec<Option<f32>>,
sizes: Vec<Option<DefiniteLength>>,
dock_area: &WeakEntity<DockArea>,
window: &mut Window,
cx: &mut App,
) -> Self {
let mut items = items;
let ratios: Vec<Option<f32>> = sizes
.into_iter()
.map(|size| size.map(|val| definite_length_to_window_ratio(val, axis, window)))
.collect();
let stack_panel = cx.new(|cx| {
let mut stack_panel = StackPanel::new(axis, window, cx);
for (i, item) in items.iter_mut().enumerate() {
@ -530,7 +552,7 @@ impl DockArea {
pub fn set_left_dock(
&mut self,
panel: DockItem,
ratio: f32,
size: impl Into<DefiniteLength>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -539,7 +561,7 @@ impl DockArea {
let weak_self = cx.entity().downgrade();
self.left_dock = Some(cx.new(|cx| {
let mut dock = Dock::left(weak_self.clone(), window, cx);
dock.set_ratio(ratio, window, cx);
dock.set_size(size, window, cx);
dock.set_panel(panel, window, cx);
dock.set_open(open, window, cx);
dock
@ -550,7 +572,7 @@ impl DockArea {
pub fn set_bottom_dock(
&mut self,
panel: DockItem,
ratio: f32,
size: impl Into<DefiniteLength>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -559,7 +581,7 @@ impl DockArea {
let weak_self = cx.entity().downgrade();
self.bottom_dock = Some(cx.new(|cx| {
let mut dock = Dock::bottom(weak_self.clone(), window, cx);
dock.set_ratio(ratio, window, cx);
dock.set_size(size, window, cx);
dock.set_panel(panel, window, cx);
dock.set_open(open, window, cx);
dock
@ -570,7 +592,7 @@ impl DockArea {
pub fn set_right_dock(
&mut self,
panel: DockItem,
ratio: f32,
size: impl Into<DefiniteLength>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -579,7 +601,7 @@ impl DockArea {
let weak_self = cx.entity().downgrade();
self.right_dock = Some(cx.new(|cx| {
let mut dock = Dock::right(weak_self.clone(), window, cx);
dock.set_ratio(ratio, window, cx);
dock.set_size(size, window, cx);
dock.set_panel(panel, window, cx);
dock.set_open(open, window, cx);
dock
@ -723,7 +745,7 @@ impl DockArea {
} else {
self.set_left_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
0.2,
relative(0.2),
true,
window,
cx,
@ -736,7 +758,7 @@ impl DockArea {
} else {
self.set_bottom_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
0.2,
relative(0.2),
true,
window,
cx,
@ -749,7 +771,7 @@ impl DockArea {
} else {
self.set_right_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
0.2,
relative(0.2),
true,
window,
cx,

View file

@ -1,4 +1,6 @@
use gpui::{point, px, size, App, AppContext, Axis, Bounds, Entity, Pixels, WeakEntity, Window};
use gpui::{
point, px, relative, size, App, AppContext, Axis, Bounds, Entity, Pixels, WeakEntity, Window,
};
use itertools::Itertools as _;
use serde::{Deserialize, Serialize};
@ -206,7 +208,7 @@ impl PanelState {
} else {
Axis::Vertical
};
let ratios = ratios.iter().map(|&ratio| Some(ratio)).collect();
let ratios = ratios.iter().map(|&ratio| Some(relative(ratio))).collect();
DockItem::split_with_sizes(axis, items, ratios, &dock_area, window, cx)
}
PanelInfo::Tabs { active_index } => {

View file

@ -1,7 +1,7 @@
use std::sync::Arc;
use gpui::{
div, prelude::FluentBuilder, px, rems, App, AppContext, Context, Corner, DefiniteLength,
div, prelude::FluentBuilder, px, relative, rems, App, AppContext, Context, Corner,
DismissEvent, DragMoveEvent, Empty, Entity, EventEmitter, FocusHandle, Focusable,
InteractiveElement as _, IntoElement, ParentElement, Render, ScrollHandle, SharedString,
StatefulInteractiveElement, StyleRefinement, Styled, WeakEntity, Window,
@ -823,7 +823,7 @@ impl TabPanel {
.bg(cx.theme().drop_target)
.map(|this| match self.will_split_placement {
Some(placement) => {
let size = DefiniteLength::Fraction(0.35);
let size = relative(0.35);
match placement {
Placement::Left => this.left_0().top_0().bottom_0().w(size),
Placement::Right => {