Fix panel resize when window resized. (#181)
Co-authored-by: Floyd Wang <gassnake999@gmail.com>
This commit is contained in:
parent
237b0f6956
commit
9768755eab
8 changed files with 55 additions and 61 deletions
|
|
@ -65,7 +65,7 @@ impl StoryWorkspace {
|
|||
let stock_panel1 = cx.new_view(|cx| StackPanel::new(Axis::Vertical, cx));
|
||||
view.add_panel(
|
||||
stock_panel1.clone(),
|
||||
Some(px(400.)),
|
||||
Some(px(380.)),
|
||||
weak_dock_area.clone(),
|
||||
cx,
|
||||
);
|
||||
|
|
@ -307,7 +307,6 @@ impl Render for StoryWorkspace {
|
|||
.relative()
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.flex_col()
|
||||
.bg(cx.theme().background)
|
||||
.text_color(cx.theme().foreground)
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use crate::{
|
|||
h_flex,
|
||||
indicator::Indicator,
|
||||
theme::{ActiveTheme, Colorize as _},
|
||||
tooltip::Tooltip,
|
||||
Disableable, Icon, Selectable, Sizable, Size,
|
||||
};
|
||||
use gpui::{
|
||||
|
|
@ -385,6 +386,9 @@ impl RenderOnce for Button {
|
|||
.children(self.children)
|
||||
})
|
||||
.when(self.loading, |this| this.bg(normal_style.bg.opacity(0.8)))
|
||||
.when_some(self.tooltip.clone(), |this, tooltip| {
|
||||
this.tooltip(move |cx| Tooltip::new(tooltip.clone(), cx))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,7 @@ impl Render for DockArea {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
div()
|
||||
.id("dock-area")
|
||||
.flex()
|
||||
.flex_grow()
|
||||
.flex_shrink()
|
||||
.size_full()
|
||||
.overflow_hidden()
|
||||
.map(|this| match self.zoom_view.clone() {
|
||||
Some(view) => this.bg(cx.theme().tab_bar).p_3().child(
|
||||
|
|
|
|||
|
|
@ -265,8 +265,6 @@ impl Render for StackPanel {
|
|||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.size_full()
|
||||
.flex_grow()
|
||||
.flex_shrink()
|
||||
.overflow_hidden()
|
||||
.bg(cx.theme().tab_bar)
|
||||
.child(self.panel_group.clone())
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
popup_menu::PopupMenuExt,
|
||||
tab::{Tab, TabBar},
|
||||
theme::ActiveTheme,
|
||||
tooltip::Tooltip,
|
||||
v_flex, AxisExt, IconName, Placement, Selectable, Sizable, StyledExt,
|
||||
};
|
||||
|
||||
|
|
@ -174,6 +175,7 @@ impl TabPanel {
|
|||
.icon(IconName::Minimize)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.tooltip(t!("Dock.Zoom Out"))
|
||||
.on_click(
|
||||
cx.listener(|view, _, cx| view.on_action_toggle_zoom(&ToggleZoom, cx)),
|
||||
),
|
||||
|
|
@ -203,6 +205,7 @@ impl TabPanel {
|
|||
|
||||
if self.panels.len() == 1 {
|
||||
let panel = self.panels.get(0).unwrap();
|
||||
let title = panel.title(cx);
|
||||
|
||||
return h_flex()
|
||||
.justify_between()
|
||||
|
|
@ -216,8 +219,9 @@ impl TabPanel {
|
|||
.px_3()
|
||||
.min_w_16()
|
||||
.overflow_hidden()
|
||||
.whitespace_nowrap()
|
||||
.child(panel.title(cx))
|
||||
.text_ellipsis()
|
||||
.child(title.clone())
|
||||
.tooltip(move |cx| Tooltip::new(title.clone(), cx))
|
||||
.on_drag(
|
||||
DragPanel {
|
||||
panel: panel.clone(),
|
||||
|
|
@ -302,6 +306,7 @@ impl TabPanel {
|
|||
.id("tab-content")
|
||||
.group("")
|
||||
.overflow_y_scroll()
|
||||
.overflow_x_hidden()
|
||||
.flex_1()
|
||||
.child(panel.view())
|
||||
.on_drag_move(cx.listener(Self::on_panel_drag_move))
|
||||
|
|
@ -500,9 +505,6 @@ impl Render for TabPanel {
|
|||
.track_focus(&self.focus_handle)
|
||||
.on_action(cx.listener(Self::on_action_toggle_zoom))
|
||||
.size_full()
|
||||
.flex_grow()
|
||||
.flex_shrink()
|
||||
.flex_none()
|
||||
.overflow_hidden()
|
||||
.bg(cx.theme().background)
|
||||
.child(self.render_tabs(cx))
|
||||
|
|
|
|||
|
|
@ -472,6 +472,8 @@ where
|
|||
}
|
||||
|
||||
fn toggle_menu(&mut self, _: &ClickEvent, cx: &mut ViewContext<Self>) {
|
||||
cx.stop_propagation();
|
||||
|
||||
self.open = !self.open;
|
||||
if self.open {
|
||||
self.list.focus_handle(cx).focus(cx);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ use std::rc::Rc;
|
|||
use gpui::{
|
||||
canvas, div, prelude::FluentBuilder, px, Along, AnyElement, AnyView, Axis, Bounds, Element,
|
||||
EntityId, InteractiveElement as _, IntoElement, MouseMoveEvent, MouseUpEvent, ParentElement,
|
||||
Pixels, Render, Size, StatefulInteractiveElement, Style, Styled, View, ViewContext,
|
||||
Pixels, Render, StatefulInteractiveElement, Style, Styled, View, ViewContext,
|
||||
VisualContext as _, WindowContext,
|
||||
};
|
||||
|
||||
use crate::{h_flex, theme::ActiveTheme, v_flex, AxisExt};
|
||||
|
||||
const PANEL_MIN_SIZE: Pixels = px(100.);
|
||||
const HANDLE_PADDING: Pixels = px(4.);
|
||||
|
||||
#[derive(Clone, Render)]
|
||||
|
|
@ -20,29 +21,29 @@ pub struct ResizablePanelGroup {
|
|||
sizes: Vec<Pixels>,
|
||||
axis: Axis,
|
||||
handle_size: Pixels,
|
||||
size: Pixels,
|
||||
size: Option<Pixels>,
|
||||
bounds: Bounds<Pixels>,
|
||||
resizing_panel_ix: Option<usize>,
|
||||
last_window_size: Size<Pixels>,
|
||||
}
|
||||
|
||||
impl ResizablePanelGroup {
|
||||
pub(super) fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
// Observe the window size to update the bounds of the resizable panel group.
|
||||
cx.observe_window_bounds(Self::on_window_resize).detach();
|
||||
|
||||
pub(super) fn new(_cx: &mut ViewContext<Self>) -> Self {
|
||||
Self {
|
||||
axis: Axis::Horizontal,
|
||||
sizes: Vec::new(),
|
||||
panels: Vec::new(),
|
||||
handle_size: px(1.),
|
||||
size: px(20.),
|
||||
size: None,
|
||||
bounds: Bounds::default(),
|
||||
resizing_panel_ix: None,
|
||||
last_window_size: cx.bounds().size,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&mut self, sizes: Vec<Pixels>, panels: Vec<View<ResizablePanel>>) {
|
||||
self.sizes = sizes;
|
||||
self.panels = panels;
|
||||
}
|
||||
|
||||
/// Set the axis of the resizable panel group, default is horizontal.
|
||||
pub fn axis(mut self, axis: Axis) -> Self {
|
||||
self.axis = axis;
|
||||
|
|
@ -63,19 +64,19 @@ impl ResizablePanelGroup {
|
|||
}
|
||||
|
||||
/// Add a resizable panel to the group.
|
||||
pub fn child(mut self, panel: ResizablePanel, cx: &mut WindowContext) -> Self {
|
||||
pub fn child(mut self, panel: ResizablePanel, cx: &mut ViewContext<Self>) -> Self {
|
||||
self.add_child(panel, cx);
|
||||
self
|
||||
}
|
||||
|
||||
/// Add a ResizablePanelGroup as a child to the group.
|
||||
pub fn group(self, group: ResizablePanelGroup, cx: &mut WindowContext) -> Self {
|
||||
pub fn group(self, group: ResizablePanelGroup, cx: &mut ViewContext<Self>) -> Self {
|
||||
let mut group: ResizablePanelGroup = group;
|
||||
group.handle_size = self.handle_size;
|
||||
let size = group.size;
|
||||
let panel = ResizablePanel::new()
|
||||
.content_view(cx.new_view(|_| group).into())
|
||||
.size(size);
|
||||
.when_some(size, |this, size| this.size(size));
|
||||
self.child(panel, cx)
|
||||
}
|
||||
|
||||
|
|
@ -84,13 +85,21 @@ impl ResizablePanelGroup {
|
|||
/// - When the axis is horizontal, the size is the height of the group.
|
||||
/// - When the axis is vertical, the size is the width of the group.
|
||||
pub fn size(mut self, size: Pixels) -> Self {
|
||||
self.size = size;
|
||||
self.size = Some(size);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, panel: ResizablePanel, cx: &mut WindowContext) {
|
||||
/// When add a child panel to the group, resize other panels each into half of the remaining space.
|
||||
fn default_panel_size(&self) -> Pixels {
|
||||
let container_size = self.bounds.size.along(self.axis);
|
||||
let each_size = container_size / (self.panels.len() + 1) as f32;
|
||||
each_size.round()
|
||||
}
|
||||
|
||||
pub fn add_child(&mut self, panel: ResizablePanel, cx: &mut ViewContext<Self>) {
|
||||
let mut panel = panel;
|
||||
panel.axis = self.axis;
|
||||
panel.size = self.default_panel_size();
|
||||
self.sizes.push(panel.size);
|
||||
self.panels.push(cx.new_view(|_| panel));
|
||||
}
|
||||
|
|
@ -98,6 +107,7 @@ impl ResizablePanelGroup {
|
|||
pub fn insert_child(&mut self, panel: ResizablePanel, ix: usize, cx: &mut ViewContext<Self>) {
|
||||
let mut panel = panel;
|
||||
panel.axis = self.axis;
|
||||
panel.size = self.default_panel_size();
|
||||
self.sizes.insert(ix, panel.size);
|
||||
self.panels.insert(ix, cx.new_view(|_| panel));
|
||||
cx.notify()
|
||||
|
|
@ -112,6 +122,7 @@ impl ResizablePanelGroup {
|
|||
) {
|
||||
let mut panel = panel;
|
||||
panel.axis = self.axis;
|
||||
panel.size = self.default_panel_size();
|
||||
self.sizes[ix] = panel.size;
|
||||
self.panels[ix] = cx.new_view(|_| panel);
|
||||
cx.notify()
|
||||
|
|
@ -129,22 +140,6 @@ impl ResizablePanelGroup {
|
|||
cx.notify()
|
||||
}
|
||||
|
||||
fn on_window_resize(&mut self, cx: &mut ViewContext<Self>) {
|
||||
let changed_size = cx.bounds().size - self.last_window_size;
|
||||
self.last_window_size = cx.bounds().size;
|
||||
let changed = changed_size.along(self.axis);
|
||||
|
||||
// Avg the change in size across all panels.
|
||||
// The minimum size limited in ResizablePanel.
|
||||
let avg_change = changed / self.panels.len() as f32;
|
||||
for (ix, panel) in self.panels.iter().enumerate() {
|
||||
self.sizes[ix] += avg_change;
|
||||
panel.update(cx, |this, _| this.size = self.sizes[ix]);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
fn render_resize_handle(&self, ix: usize, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let axis = self.axis;
|
||||
let neg_offset = -HANDLE_PADDING + px(1.);
|
||||
|
|
@ -253,7 +248,7 @@ impl ResizablePanelGroup {
|
|||
}
|
||||
|
||||
self.sizes = new_sizes;
|
||||
for (i, panel) in self.panels.iter_mut().enumerate() {
|
||||
for (i, panel) in self.panels.iter().enumerate() {
|
||||
let size = self.sizes[i];
|
||||
panel.update(cx, |this, _| this.size = size);
|
||||
}
|
||||
|
|
@ -271,15 +266,6 @@ impl Render for ResizablePanelGroup {
|
|||
|
||||
container
|
||||
.size_full()
|
||||
.flex_grow()
|
||||
.flex_shrink()
|
||||
// .map(|this| {
|
||||
// use crate::StyledExt as _;
|
||||
// match self.axis {
|
||||
// Axis::Horizontal => this.debug_red(),
|
||||
// Axis::Vertical => this.debug_blue(),
|
||||
// }
|
||||
// })
|
||||
.children(self.panels.iter().enumerate().map(|(ix, panel)| {
|
||||
if ix < self.panels.len() - 1 {
|
||||
let handle = self.render_resize_handle(ix, cx);
|
||||
|
|
@ -305,8 +291,6 @@ impl Render for ResizablePanelGroup {
|
|||
}
|
||||
}
|
||||
|
||||
const PANEL_MIN_SIZE: Pixels = px(100.);
|
||||
|
||||
pub struct ResizablePanel {
|
||||
size: Pixels,
|
||||
axis: Axis,
|
||||
|
|
@ -320,7 +304,7 @@ pub struct ResizablePanel {
|
|||
impl ResizablePanel {
|
||||
pub(super) fn new() -> Self {
|
||||
Self {
|
||||
size: px(20.),
|
||||
size: PANEL_MIN_SIZE,
|
||||
axis: Axis::Horizontal,
|
||||
content_builder: None,
|
||||
content_view: None,
|
||||
|
|
@ -353,18 +337,24 @@ impl FluentBuilder for ResizablePanel {}
|
|||
impl Render for ResizablePanel {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let view = cx.view().clone();
|
||||
let axis = self.axis;
|
||||
let size = self.size.max(PANEL_MIN_SIZE);
|
||||
|
||||
div()
|
||||
.relative()
|
||||
.size_full()
|
||||
.flex()
|
||||
.flex_grow()
|
||||
.flex_shrink()
|
||||
.when(self.axis.is_vertical(), |this| this.h(size))
|
||||
.when(self.axis.is_horizontal(), |this| this.w(size))
|
||||
.relative()
|
||||
.overflow_hidden()
|
||||
.when(self.axis.is_vertical(), |this| this.w_full().h(size))
|
||||
.when(self.axis.is_horizontal(), |this| this.h_full().w(size))
|
||||
.child({
|
||||
canvas(
|
||||
move |bounds, cx| view.update(cx, |r, _| r.bounds = bounds),
|
||||
move |bounds, cx| {
|
||||
view.update(cx, |r, _| {
|
||||
r.size = bounds.size.along(axis);
|
||||
r.bounds = bounds;
|
||||
})
|
||||
},
|
||||
|_, _, _| {},
|
||||
)
|
||||
.absolute()
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ impl RenderOnce for Tab {
|
|||
.items_center()
|
||||
.flex_shrink_0()
|
||||
.cursor_pointer()
|
||||
.overflow_hidden()
|
||||
.text_color(text_color)
|
||||
.bg(bg_color)
|
||||
.border_x_1()
|
||||
|
|
|
|||
Loading…
Reference in a new issue