ui/components/resizable/
mod.rs1mod group;
9
10use gpui::{AnyElement, Axis, Div, Stateful};
11use smallvec::SmallVec;
12
13pub use group::{ResizablePanelGroup, ResizablePreview};
14
15use crate::prelude::*;
16
17#[derive(IntoElement)]
20pub struct ResizablePanel {
21 children: SmallVec<[AnyElement; 2]>,
22 fraction: f32,
23 axis: Axis,
24}
25
26impl ResizablePanel {
27 pub fn new() -> Self {
31 Self {
32 children: SmallVec::new(),
33 fraction: 1.0,
34 axis: Axis::Horizontal,
35 }
36 }
37
38 pub(crate) fn fraction(mut self, fraction: f32) -> Self {
39 self.fraction = fraction;
40 self
41 }
42
43 pub fn axis(mut self, axis: Axis) -> Self {
46 self.axis = axis;
47 self
48 }
49}
50
51impl Default for ResizablePanel {
52 fn default() -> Self {
53 Self::new()
54 }
55}
56
57impl ParentElement for ResizablePanel {
58 fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
59 self.children.extend(elements);
60 }
61}
62
63impl RenderOnce for ResizablePanel {
64 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
65 let is_horizontal = self.axis == Axis::Horizontal;
66 div()
67 .when(is_horizontal, |this| this.h_full())
68 .when(!is_horizontal, |this| this.w_full())
69 .overflow_hidden()
70 .when(self.fraction >= 1.0, |this| this.flex_grow())
71 .when(self.fraction < 1.0 && is_horizontal, |this| {
72 this.flex_shrink_0().w(relative(self.fraction))
73 })
74 .when(self.fraction < 1.0 && !is_horizontal, |this| {
75 this.flex_shrink_0().h(relative(self.fraction))
76 })
77 .bg(semantic::surface(cx))
78 .children(self.children)
79 }
80}
81
82#[derive(IntoElement)]
86pub struct ResizableHandle {
87 div: Stateful<Div>,
88 axis: Axis,
89}
90
91impl ResizableHandle {
92 pub fn new(id: impl Into<ElementId>) -> Self {
95 Self {
96 div: div().id(id),
97 axis: Axis::Horizontal,
98 }
99 }
100
101 pub fn axis(mut self, axis: Axis) -> Self {
106 self.axis = axis;
107 self
108 }
109}
110
111impl InteractiveElement for ResizableHandle {
112 fn interactivity(&mut self) -> &mut gpui::Interactivity {
113 self.div.interactivity()
114 }
115}
116
117impl StatefulInteractiveElement for ResizableHandle {}
118
119impl RenderOnce for ResizableHandle {
120 fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
121 let is_horizontal = self.axis == Axis::Horizontal;
122 let line = div()
123 .when(is_horizontal, |this| this.w(px(1.)).h_full())
124 .when(!is_horizontal, |this| this.h(px(1.)).w_full())
125 .bg(semantic::border(cx));
126
127 self.div
128 .flex_shrink_0()
129 .flex()
130 .items_center()
131 .justify_center()
132 .when(is_horizontal, |this| {
133 this.w(px(8.)).h_full().cursor_col_resize()
134 })
135 .when(!is_horizontal, |this| {
136 this.h(px(8.)).w_full().cursor_row_resize()
137 })
138 .child(line)
139 }
140}