dock: Revert dock to use absolute size. (#840)

This change to revert `Dock` to use `Pixels` for size, not use ratio,
because in most case we need to keep dock size, not wants it change when
window resize, we just only want center dock to change.

The `Panel` will keep the relative size changes.
This commit is contained in:
Jason Lee 2025-05-08 16:29:55 +08:00 committed by GitHub
parent a26311dc0e
commit f8e30c6f5d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 37 additions and 86 deletions

View file

@ -279,7 +279,7 @@ impl StoryWorkspace {
cx,
),
],
vec![None, Some(relative(0.2))],
vec![None, Some(0.2)],
&dock_area,
window,
cx,
@ -328,8 +328,8 @@ 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, relative(0.3), true, window, cx);
view.set_bottom_dock(bottom_panels, relative(0.2), true, window, cx);
view.set_left_dock(left_panels, px(300.), true, window, cx);
view.set_bottom_dock(bottom_panels, px(200.), 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, DefiniteLength,
Element, Empty, Entity, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement as _, Pixels,
Point, Render, Style, StyleRefinement, Styled as _, WeakEntity, Window,
div, prelude::FluentBuilder as _, px, App, AppContext, Axis, Context, 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::{definite_length_to_window_ratio, DockArea, DockItem, PanelView, TabPanel};
use super::{DockArea, DockItem, PanelView, TabPanel};
#[derive(Clone)]
struct ResizePanel;
@ -66,8 +66,8 @@ pub struct Dock {
pub(super) placement: DockPlacement,
dock_area: WeakEntity<DockArea>,
pub(crate) panel: DockItem,
/// The ratio of the dock.
pub(super) ratio: f32,
/// The size of the dock.
pub(super) size: Pixels,
pub(super) open: bool,
/// Whether the Dock is collapsible, default: true
pub(super) collapsible: bool,
@ -104,7 +104,7 @@ impl Dock {
panel,
open: true,
collapsible: true,
ratio: 0.2,
size: px(200.),
resizing: false,
}
}
@ -147,7 +147,7 @@ impl Dock {
pub(super) fn from_state(
dock_area: WeakEntity<DockArea>,
placement: DockPlacement,
ratio: f32,
size: impl Into<Pixels>,
panel: DockItem,
open: bool,
window: &mut Window,
@ -176,7 +176,7 @@ impl Dock {
dock_area,
panel,
open,
ratio,
size: size.into(),
collapsible: true,
resizing: false,
}
@ -244,18 +244,13 @@ impl Dock {
/// Returns the size of the Dock, the size is means the width or height of
/// the Dock, if the placement is left or right, the size is width,
/// otherwise the size is height.
pub fn ratio(&self) -> f32 {
self.ratio
pub fn size(&self) -> Pixels {
self.size
}
/// Set the size of the Dock.
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);
pub fn set_size(&mut self, size: impl Into<Pixels>, _: &mut Window, cx: &mut Context<Self>) {
self.size = size.into();
cx.notify();
}
@ -292,16 +287,6 @@ impl Dock {
cx.notify();
}
fn container_size(&self, cx: &App) -> Pixels {
let dock_area = self
.dock_area
.upgrade()
.expect("DockArea is missing")
.read(cx);
let area_bounds = dock_area.bounds;
area_bounds.size.along(self.placement.axis())
}
fn render_resize_handle(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
let axis = self.placement.axis();
let view = cx.entity().clone();
@ -335,10 +320,7 @@ impl Dock {
DockPlacement::Bottom => area_bounds.bottom() - mouse_position.y,
DockPlacement::Center => unreachable!(),
};
let container_size = self.container_size(cx);
let ratio = size / container_size;
let min_ratio = PANEL_MIN_SIZE / container_size;
self.ratio = ratio.clamp(min_ratio, 1.);
self.size = size.max(PANEL_MIN_SIZE);
cx.notify();
}
@ -355,8 +337,7 @@ impl Render for Dock {
}
let cache_style = StyleRefinement::default().absolute().size_full();
let container_size = self.container_size(cx);
let dock_size = (self.ratio * container_size).max(PANEL_MIN_SIZE);
let dock_size = self.size;
div()
.relative()

View file

@ -8,10 +8,9 @@ mod tiles;
use anyhow::Result;
use gpui::{
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,
actions, canvas, div, prelude::FluentBuilder, px, AnyElement, AnyView, App, AppContext, Axis,
Bounds, Context, Edges, Entity, EntityId, EventEmitter, InteractiveElement as _, IntoElement,
ParentElement as _, Pixels, Render, SharedString, Styled, Subscription, WeakEntity, Window,
};
use std::sync::Arc;
@ -28,22 +27,6 @@ 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.
///
@ -155,22 +138,17 @@ impl DockItem {
/// Create DockItem with split layout, each item of panel have specified size.
///
/// Please note that the `items` and `sizes` must have the same length.
/// Please note that the `items` and `ratios` must have the same length.
/// Set `None` in `sizes` to make the index of panel have auto size.
pub fn split_with_sizes(
axis: Axis,
items: Vec<DockItem>,
sizes: Vec<Option<DefiniteLength>>,
ratios: Vec<Option<f32>>,
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() {
@ -552,7 +530,7 @@ impl DockArea {
pub fn set_left_dock(
&mut self,
panel: DockItem,
size: impl Into<DefiniteLength>,
size: impl Into<Pixels>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -572,7 +550,7 @@ impl DockArea {
pub fn set_bottom_dock(
&mut self,
panel: DockItem,
size: impl Into<DefiniteLength>,
size: impl Into<Pixels>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -592,7 +570,7 @@ impl DockArea {
pub fn set_right_dock(
&mut self,
panel: DockItem,
size: impl Into<DefiniteLength>,
size: impl Into<Pixels>,
open: bool,
window: &mut Window,
cx: &mut Context<Self>,
@ -745,7 +723,7 @@ impl DockArea {
} else {
self.set_left_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
relative(0.2),
px(200.),
true,
window,
cx,
@ -758,7 +736,7 @@ impl DockArea {
} else {
self.set_bottom_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
relative(0.2),
px(200.),
true,
window,
cx,
@ -771,7 +749,7 @@ impl DockArea {
} else {
self.set_right_dock(
DockItem::tabs(vec![panel], None, &weak_self, window, cx),
relative(0.2),
px(200.),
true,
window,
cx,

View file

@ -1,6 +1,4 @@
use gpui::{
point, px, relative, size, App, AppContext, Axis, Bounds, Entity, Pixels, WeakEntity, Window,
};
use gpui::{point, px, size, App, AppContext, Axis, Bounds, Entity, Pixels, WeakEntity, Window};
use itertools::Itertools as _;
use serde::{Deserialize, Serialize};
@ -28,22 +26,17 @@ pub struct DockAreaState {
pub struct DockState {
panel: PanelState,
placement: DockPlacement,
#[serde(default = "default_ratio")]
ratio: f32,
size: Pixels,
open: bool,
}
fn default_ratio() -> f32 {
0.2
}
impl DockState {
pub fn new(dock: Entity<Dock>, cx: &App) -> Self {
let dock = dock.read(cx);
Self {
placement: dock.placement,
ratio: dock.ratio,
size: dock.size,
open: dock.open,
panel: dock.panel.view().dump(cx),
}
@ -61,7 +54,7 @@ impl DockState {
Dock::from_state(
dock_area.clone(),
self.placement,
self.ratio,
self.size,
item,
self.open,
window,
@ -208,7 +201,7 @@ impl PanelState {
} else {
Axis::Vertical
};
let ratios = ratios.iter().map(|&ratio| Some(relative(ratio))).collect();
let ratios = ratios.iter().map(|&ratio| Some(ratio)).collect();
DockItem::split_with_sizes(axis, items, ratios, &dock_area, window, cx)
}
PanelInfo::Tabs { active_index } => {
@ -265,7 +258,7 @@ mod tests {
let left_dock = state.left_dock.unwrap();
assert_eq!(left_dock.open, true);
assert_eq!(left_dock.ratio, 0.2);
assert_eq!(left_dock.size, px(350.));
assert_eq!(left_dock.placement, DockPlacement::Left);
assert_eq!(left_dock.panel.panel_name, "TabPanel");
assert_eq!(left_dock.panel.children.len(), 1);
@ -273,14 +266,14 @@ mod tests {
let bottom_dock = state.bottom_dock.unwrap();
assert_eq!(bottom_dock.open, true);
assert_eq!(bottom_dock.ratio, 0.32);
assert_eq!(bottom_dock.size, px(200.));
assert_eq!(bottom_dock.panel.panel_name, "TabPanel");
assert_eq!(bottom_dock.panel.children.len(), 2);
assert_eq!(bottom_dock.panel.children[0].panel_name, "StoryContainer");
let right_dock = state.right_dock.unwrap();
assert_eq!(right_dock.open, true);
assert_eq!(right_dock.ratio, 0.2);
assert_eq!(right_dock.size, px(320.));
assert_eq!(right_dock.panel.panel_name, "TabPanel");
assert_eq!(right_dock.panel.children.len(), 1);
assert_eq!(right_dock.panel.children[0].panel_name, "StoryContainer");

View file

@ -255,7 +255,6 @@
},
"placement": "bottom",
"size": 200.0,
"ratio": 0.32,
"open": true,
"resizeable": true
}