1use crate::{AppState, FollowerState, Pane, Workspace};
2use anyhow::{anyhow, Result};
3use call2::ActiveCall;
4use collections::HashMap;
5use gpui2::{point, size, AnyElement, AnyView, Bounds, Model, Pixels, Point, View, ViewContext};
6use parking_lot::Mutex;
7use project2::Project;
8use serde::Deserialize;
9use std::sync::Arc;
10use theme2::Theme;
11
12const HANDLE_HITBOX_SIZE: f32 = 4.0;
13const HORIZONTAL_MIN_SIZE: f32 = 80.;
14const VERTICAL_MIN_SIZE: f32 = 100.;
15
16#[derive(Copy, Clone, PartialEq, Eq)]
17pub enum Axis {
18 Vertical,
19 Horizontal,
20}
21
22#[derive(Clone, PartialEq)]
23pub struct PaneGroup {
24 pub(crate) root: Member,
25}
26
27impl PaneGroup {
28 pub(crate) fn with_root(root: Member) -> Self {
29 Self { root }
30 }
31
32 pub fn new(pane: View<Pane>) -> Self {
33 Self {
34 root: Member::Pane(pane),
35 }
36 }
37
38 pub fn split(
39 &mut self,
40 old_pane: &View<Pane>,
41 new_pane: &View<Pane>,
42 direction: SplitDirection,
43 ) -> Result<()> {
44 match &mut self.root {
45 Member::Pane(pane) => {
46 if pane == old_pane {
47 self.root = Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
48 Ok(())
49 } else {
50 Err(anyhow!("Pane not found"))
51 }
52 }
53 Member::Axis(axis) => axis.split(old_pane, new_pane, direction),
54 }
55 }
56
57 pub fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
58 match &self.root {
59 Member::Pane(_) => None,
60 Member::Axis(axis) => axis.bounding_box_for_pane(pane),
61 }
62 }
63
64 pub fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
65 match &self.root {
66 Member::Pane(pane) => Some(pane),
67 Member::Axis(axis) => axis.pane_at_pixel_position(coordinate),
68 }
69 }
70
71 /// Returns:
72 /// - Ok(true) if it found and removed a pane
73 /// - Ok(false) if it found but did not remove the pane
74 /// - Err(_) if it did not find the pane
75 pub fn remove(&mut self, pane: &View<Pane>) -> Result<bool> {
76 match &mut self.root {
77 Member::Pane(_) => Ok(false),
78 Member::Axis(axis) => {
79 if let Some(last_pane) = axis.remove(pane)? {
80 self.root = last_pane;
81 }
82 Ok(true)
83 }
84 }
85 }
86
87 pub fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
88 match &mut self.root {
89 Member::Pane(_) => {}
90 Member::Axis(axis) => axis.swap(from, to),
91 };
92 }
93
94 pub(crate) fn render(
95 &self,
96 project: &Model<Project>,
97 theme: &Theme,
98 follower_states: &HashMap<View<Pane>, FollowerState>,
99 active_call: Option<&Model<ActiveCall>>,
100 active_pane: &View<Pane>,
101 zoomed: Option<&AnyView>,
102 app_state: &Arc<AppState>,
103 cx: &mut ViewContext<Workspace>,
104 ) -> AnyElement<Workspace> {
105 self.root.render(
106 project,
107 0,
108 theme,
109 follower_states,
110 active_call,
111 active_pane,
112 zoomed,
113 app_state,
114 cx,
115 )
116 }
117
118 pub(crate) fn panes(&self) -> Vec<&View<Pane>> {
119 let mut panes = Vec::new();
120 self.root.collect_panes(&mut panes);
121 panes
122 }
123}
124
125#[derive(Clone, PartialEq)]
126pub(crate) enum Member {
127 Axis(PaneAxis),
128 Pane(View<Pane>),
129}
130
131impl Member {
132 fn new_axis(old_pane: View<Pane>, new_pane: View<Pane>, direction: SplitDirection) -> Self {
133 use Axis::*;
134 use SplitDirection::*;
135
136 let axis = match direction {
137 Up | Down => Vertical,
138 Left | Right => Horizontal,
139 };
140
141 let members = match direction {
142 Up | Left => vec![Member::Pane(new_pane), Member::Pane(old_pane)],
143 Down | Right => vec![Member::Pane(old_pane), Member::Pane(new_pane)],
144 };
145
146 Member::Axis(PaneAxis::new(axis, members))
147 }
148
149 fn contains(&self, needle: &View<Pane>) -> bool {
150 match self {
151 Member::Axis(axis) => axis.members.iter().any(|member| member.contains(needle)),
152 Member::Pane(pane) => pane == needle,
153 }
154 }
155
156 pub fn render(
157 &self,
158 project: &Model<Project>,
159 basis: usize,
160 theme: &Theme,
161 follower_states: &HashMap<View<Pane>, FollowerState>,
162 active_call: Option<&Model<ActiveCall>>,
163 active_pane: &View<Pane>,
164 zoomed: Option<&AnyView>,
165 app_state: &Arc<AppState>,
166 cx: &mut ViewContext<Workspace>,
167 ) -> AnyElement<Workspace> {
168 todo!()
169
170 // enum FollowIntoExternalProject {}
171
172 // match self {
173 // Member::Pane(pane) => {
174 // let pane_element = if Some(&**pane) == zoomed {
175 // Empty::new().into_any()
176 // } else {
177 // ChildView::new(pane, cx).into_any()
178 // };
179
180 // let leader = follower_states.get(pane).and_then(|state| {
181 // let room = active_call?.read(cx).room()?.read(cx);
182 // room.remote_participant_for_peer_id(state.leader_id)
183 // });
184
185 // let mut leader_border = Border::default();
186 // let mut leader_status_box = None;
187 // if let Some(leader) = &leader {
188 // let leader_color = theme
189 // .editor
190 // .selection_style_for_room_participant(leader.participant_index.0)
191 // .cursor;
192 // leader_border = Border::all(theme.workspace.leader_border_width, leader_color);
193 // leader_border
194 // .color
195 // .fade_out(1. - theme.workspace.leader_border_opacity);
196 // leader_border.overlay = true;
197
198 // leader_status_box = match leader.location {
199 // ParticipantLocation::SharedProject {
200 // project_id: leader_project_id,
201 // } => {
202 // if Some(leader_project_id) == project.read(cx).remote_id() {
203 // None
204 // } else {
205 // let leader_user = leader.user.clone();
206 // let leader_user_id = leader.user.id;
207 // Some(
208 // MouseEventHandler::new::<FollowIntoExternalProject, _>(
209 // pane.id(),
210 // cx,
211 // |_, _| {
212 // Label::new(
213 // format!(
214 // "Follow {} to their active project",
215 // leader_user.github_login,
216 // ),
217 // theme
218 // .workspace
219 // .external_location_message
220 // .text
221 // .clone(),
222 // )
223 // .contained()
224 // .with_style(
225 // theme.workspace.external_location_message.container,
226 // )
227 // },
228 // )
229 // .with_cursor_style(CursorStyle::PointingHand)
230 // .on_click(MouseButton::Left, move |_, this, cx| {
231 // crate::join_remote_project(
232 // leader_project_id,
233 // leader_user_id,
234 // this.app_state().clone(),
235 // cx,
236 // )
237 // .detach_and_log_err(cx);
238 // })
239 // .aligned()
240 // .bottom()
241 // .right()
242 // .into_any(),
243 // )
244 // }
245 // }
246 // ParticipantLocation::UnsharedProject => Some(
247 // Label::new(
248 // format!(
249 // "{} is viewing an unshared Zed project",
250 // leader.user.github_login
251 // ),
252 // theme.workspace.external_location_message.text.clone(),
253 // )
254 // .contained()
255 // .with_style(theme.workspace.external_location_message.container)
256 // .aligned()
257 // .bottom()
258 // .right()
259 // .into_any(),
260 // ),
261 // ParticipantLocation::External => Some(
262 // Label::new(
263 // format!(
264 // "{} is viewing a window outside of Zed",
265 // leader.user.github_login
266 // ),
267 // theme.workspace.external_location_message.text.clone(),
268 // )
269 // .contained()
270 // .with_style(theme.workspace.external_location_message.container)
271 // .aligned()
272 // .bottom()
273 // .right()
274 // .into_any(),
275 // ),
276 // };
277 // }
278
279 // Stack::new()
280 // .with_child(pane_element.contained().with_border(leader_border))
281 // .with_children(leader_status_box)
282 // .into_any()
283 // }
284 // Member::Axis(axis) => axis.render(
285 // project,
286 // basis + 1,
287 // theme,
288 // follower_states,
289 // active_call,
290 // active_pane,
291 // zoomed,
292 // app_state,
293 // cx,
294 // ),
295 // }
296 }
297
298 fn collect_panes<'a>(&'a self, panes: &mut Vec<&'a View<Pane>>) {
299 match self {
300 Member::Axis(axis) => {
301 for member in &axis.members {
302 member.collect_panes(panes);
303 }
304 }
305 Member::Pane(pane) => panes.push(pane),
306 }
307 }
308}
309
310#[derive(Clone)]
311pub(crate) struct PaneAxis {
312 pub axis: Axis,
313 pub members: Vec<Member>,
314 pub flexes: Arc<Mutex<Vec<f32>>>,
315 pub bounding_boxes: Arc<Mutex<Vec<Option<Bounds<Pixels>>>>>,
316}
317
318impl PartialEq for PaneAxis {
319 fn eq(&self, other: &Self) -> bool {
320 todo!()
321 }
322}
323
324impl PaneAxis {
325 pub fn new(axis: Axis, members: Vec<Member>) -> Self {
326 let flexes = Arc::new(Mutex::new(vec![1.; members.len()]));
327 let bounding_boxes = Arc::new(Mutex::new(vec![None; members.len()]));
328 Self {
329 axis,
330 members,
331 flexes,
332 bounding_boxes,
333 }
334 }
335
336 pub fn load(axis: Axis, members: Vec<Member>, flexes: Option<Vec<f32>>) -> Self {
337 let flexes = flexes.unwrap_or_else(|| vec![1.; members.len()]);
338 debug_assert!(members.len() == flexes.len());
339
340 let flexes = Arc::new(Mutex::new(flexes));
341 let bounding_boxes = Arc::new(Mutex::new(vec![None; members.len()]));
342 Self {
343 axis,
344 members,
345 flexes,
346 bounding_boxes,
347 }
348 }
349
350 fn split(
351 &mut self,
352 old_pane: &View<Pane>,
353 new_pane: &View<Pane>,
354 direction: SplitDirection,
355 ) -> Result<()> {
356 for (mut idx, member) in self.members.iter_mut().enumerate() {
357 match member {
358 Member::Axis(axis) => {
359 if axis.split(old_pane, new_pane, direction).is_ok() {
360 return Ok(());
361 }
362 }
363 Member::Pane(pane) => {
364 if pane == old_pane {
365 if direction.axis() == self.axis {
366 if direction.increasing() {
367 idx += 1;
368 }
369
370 self.members.insert(idx, Member::Pane(new_pane.clone()));
371 *self.flexes.lock() = vec![1.; self.members.len()];
372 } else {
373 *member =
374 Member::new_axis(old_pane.clone(), new_pane.clone(), direction);
375 }
376 return Ok(());
377 }
378 }
379 }
380 }
381 Err(anyhow!("Pane not found"))
382 }
383
384 fn remove(&mut self, pane_to_remove: &View<Pane>) -> Result<Option<Member>> {
385 let mut found_pane = false;
386 let mut remove_member = None;
387 for (idx, member) in self.members.iter_mut().enumerate() {
388 match member {
389 Member::Axis(axis) => {
390 if let Ok(last_pane) = axis.remove(pane_to_remove) {
391 if let Some(last_pane) = last_pane {
392 *member = last_pane;
393 }
394 found_pane = true;
395 break;
396 }
397 }
398 Member::Pane(pane) => {
399 if pane == pane_to_remove {
400 found_pane = true;
401 remove_member = Some(idx);
402 break;
403 }
404 }
405 }
406 }
407
408 if found_pane {
409 if let Some(idx) = remove_member {
410 self.members.remove(idx);
411 *self.flexes.lock() = vec![1.; self.members.len()];
412 }
413
414 if self.members.len() == 1 {
415 let result = self.members.pop();
416 *self.flexes.lock() = vec![1.; self.members.len()];
417 Ok(result)
418 } else {
419 Ok(None)
420 }
421 } else {
422 Err(anyhow!("Pane not found"))
423 }
424 }
425
426 fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
427 for member in self.members.iter_mut() {
428 match member {
429 Member::Axis(axis) => axis.swap(from, to),
430 Member::Pane(pane) => {
431 if pane == from {
432 *member = Member::Pane(to.clone());
433 } else if pane == to {
434 *member = Member::Pane(from.clone())
435 }
436 }
437 }
438 }
439 }
440
441 fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
442 debug_assert!(self.members.len() == self.bounding_boxes.lock().len());
443
444 for (idx, member) in self.members.iter().enumerate() {
445 match member {
446 Member::Pane(found) => {
447 if pane == found {
448 return self.bounding_boxes.lock()[idx];
449 }
450 }
451 Member::Axis(axis) => {
452 if let Some(rect) = axis.bounding_box_for_pane(pane) {
453 return Some(rect);
454 }
455 }
456 }
457 }
458 None
459 }
460
461 fn pane_at_pixel_position(&self, coordinate: Point<Pixels>) -> Option<&View<Pane>> {
462 debug_assert!(self.members.len() == self.bounding_boxes.lock().len());
463
464 let bounding_boxes = self.bounding_boxes.lock();
465
466 for (idx, member) in self.members.iter().enumerate() {
467 if let Some(coordinates) = bounding_boxes[idx] {
468 if coordinates.contains_point(&coordinate) {
469 return match member {
470 Member::Pane(found) => Some(found),
471 Member::Axis(axis) => axis.pane_at_pixel_position(coordinate),
472 };
473 }
474 }
475 }
476 None
477 }
478
479 fn render(
480 &self,
481 project: &Model<Project>,
482 basis: usize,
483 theme: &Theme,
484 follower_states: &HashMap<View<Pane>, FollowerState>,
485 active_call: Option<&Model<ActiveCall>>,
486 active_pane: &View<Pane>,
487 zoomed: Option<&AnyView>,
488 app_state: &Arc<AppState>,
489 cx: &mut ViewContext<Workspace>,
490 ) -> AnyElement<Workspace> {
491 debug_assert!(self.members.len() == self.flexes.lock().len());
492
493 todo!()
494 // let mut pane_axis = PaneAxisElement::new(
495 // self.axis,
496 // basis,
497 // self.flexes.clone(),
498 // self.bounding_boxes.clone(),
499 // );
500 // let mut active_pane_ix = None;
501
502 // let mut members = self.members.iter().enumerate().peekable();
503 // while let Some((ix, member)) = members.next() {
504 // let last = members.peek().is_none();
505
506 // if member.contains(active_pane) {
507 // active_pane_ix = Some(ix);
508 // }
509
510 // let mut member = member.render(
511 // project,
512 // (basis + ix) * 10,
513 // theme,
514 // follower_states,
515 // active_call,
516 // active_pane,
517 // zoomed,
518 // app_state,
519 // cx,
520 // );
521
522 // if !last {
523 // let mut border = theme.workspace.pane_divider;
524 // border.left = false;
525 // border.right = false;
526 // border.top = false;
527 // border.bottom = false;
528
529 // match self.axis {
530 // Axis::Vertical => border.bottom = true,
531 // Axis::Horizontal => border.right = true,
532 // }
533
534 // member = member.contained().with_border(border).into_any();
535 // }
536
537 // pane_axis = pane_axis.with_child(member.into_any());
538 // }
539 // pane_axis.set_active_pane(active_pane_ix);
540 // pane_axis.into_any()
541 }
542}
543
544#[derive(Clone, Copy, Debug, Deserialize, PartialEq)]
545pub enum SplitDirection {
546 Up,
547 Down,
548 Left,
549 Right,
550}
551
552impl SplitDirection {
553 pub fn all() -> [Self; 4] {
554 [Self::Up, Self::Down, Self::Left, Self::Right]
555 }
556
557 pub fn edge(&self, rect: Bounds<Pixels>) -> Pixels {
558 match self {
559 Self::Up => rect.origin.y,
560 Self::Down => rect.lower_left().y,
561 Self::Left => rect.lower_left().x,
562 Self::Right => rect.lower_right().x,
563 }
564 }
565
566 pub fn along_edge(&self, bounds: Bounds<Pixels>, length: Pixels) -> Bounds<Pixels> {
567 match self {
568 Self::Up => Bounds {
569 origin: bounds.origin,
570 size: size(bounds.size.width, length),
571 },
572 Self::Down => Bounds {
573 origin: point(bounds.lower_left().x, bounds.lower_left().y - length),
574 size: size(bounds.size.width, length),
575 },
576 Self::Left => Bounds {
577 origin: bounds.origin,
578 size: size(length, bounds.size.height),
579 },
580 Self::Right => Bounds {
581 origin: point(bounds.lower_right().x - length, bounds.lower_left().y),
582 size: size(length, bounds.size.height),
583 },
584 }
585 }
586
587 pub fn axis(&self) -> Axis {
588 match self {
589 Self::Up | Self::Down => Axis::Vertical,
590 Self::Left | Self::Right => Axis::Horizontal,
591 }
592 }
593
594 pub fn increasing(&self) -> bool {
595 match self {
596 Self::Left | Self::Up => false,
597 Self::Down | Self::Right => true,
598 }
599 }
600}
601
602// mod element {
603// // use std::{cell::RefCell, iter::from_fn, ops::Range, rc::Rc};
604
605// // use gpui::{
606// // geometry::{
607// // rect::Bounds<Pixels>,
608// // vector::{vec2f, Vector2F},
609// // },
610// // json::{self, ToJson},
611// // platform::{CursorStyle, MouseButton},
612// // scene::MouseDrag,
613// // AnyElement, Axis, CursorRegion, Element, EventContext, MouseRegion, Bounds<Pixels>Ext,
614// // SizeConstraint, Vector2FExt, ViewContext,
615// // };
616
617// use crate::{
618// pane_group::{HANDLE_HITBOX_SIZE, HORIZONTAL_MIN_SIZE, VERTICAL_MIN_SIZE},
619// Workspace, WorkspaceSettings,
620// };
621
622// pub struct PaneAxisElement {
623// axis: Axis,
624// basis: usize,
625// active_pane_ix: Option<usize>,
626// flexes: Rc<RefCell<Vec<f32>>>,
627// children: Vec<AnyElement<Workspace>>,
628// bounding_boxes: Rc<RefCell<Vec<Option<Bounds<Pixels>>>>>,
629// }
630
631// impl PaneAxisElement {
632// pub fn new(
633// axis: Axis,
634// basis: usize,
635// flexes: Rc<RefCell<Vec<f32>>>,
636// bounding_boxes: Rc<RefCell<Vec<Option<Bounds<Pixels>>>>>,
637// ) -> Self {
638// Self {
639// axis,
640// basis,
641// flexes,
642// bounding_boxes,
643// active_pane_ix: None,
644// children: Default::default(),
645// }
646// }
647
648// pub fn set_active_pane(&mut self, active_pane_ix: Option<usize>) {
649// self.active_pane_ix = active_pane_ix;
650// }
651
652// fn layout_children(
653// &mut self,
654// active_pane_magnification: f32,
655// constraint: SizeConstraint,
656// remaining_space: &mut f32,
657// remaining_flex: &mut f32,
658// cross_axis_max: &mut f32,
659// view: &mut Workspace,
660// cx: &mut ViewContext<Workspace>,
661// ) {
662// let flexes = self.flexes.borrow();
663// let cross_axis = self.axis.invert();
664// for (ix, child) in self.children.iter_mut().enumerate() {
665// let flex = if active_pane_magnification != 1. {
666// if let Some(active_pane_ix) = self.active_pane_ix {
667// if ix == active_pane_ix {
668// active_pane_magnification
669// } else {
670// 1.
671// }
672// } else {
673// 1.
674// }
675// } else {
676// flexes[ix]
677// };
678
679// let child_size = if *remaining_flex == 0.0 {
680// *remaining_space
681// } else {
682// let space_per_flex = *remaining_space / *remaining_flex;
683// space_per_flex * flex
684// };
685
686// let child_constraint = match self.axis {
687// Axis::Horizontal => SizeConstraint::new(
688// vec2f(child_size, constraint.min.y()),
689// vec2f(child_size, constraint.max.y()),
690// ),
691// Axis::Vertical => SizeConstraint::new(
692// vec2f(constraint.min.x(), child_size),
693// vec2f(constraint.max.x(), child_size),
694// ),
695// };
696// let child_size = child.layout(child_constraint, view, cx);
697// *remaining_space -= child_size.along(self.axis);
698// *remaining_flex -= flex;
699// *cross_axis_max = cross_axis_max.max(child_size.along(cross_axis));
700// }
701// }
702
703// fn handle_resize(
704// flexes: Rc<RefCell<Vec<f32>>>,
705// axis: Axis,
706// preceding_ix: usize,
707// child_start: Vector2F,
708// drag_bounds: Bounds<Pixels>,
709// ) -> impl Fn(MouseDrag, &mut Workspace, &mut EventContext<Workspace>) {
710// let size = move |ix, flexes: &[f32]| {
711// drag_bounds.length_along(axis) * (flexes[ix] / flexes.len() as f32)
712// };
713
714// move |drag, workspace: &mut Workspace, cx| {
715// if drag.end {
716// // TODO: Clear cascading resize state
717// return;
718// }
719// let min_size = match axis {
720// Axis::Horizontal => HORIZONTAL_MIN_SIZE,
721// Axis::Vertical => VERTICAL_MIN_SIZE,
722// };
723// let mut flexes = flexes.borrow_mut();
724
725// // Don't allow resizing to less than the minimum size, if elements are already too small
726// if min_size - 1. > size(preceding_ix, flexes.as_slice()) {
727// return;
728// }
729
730// let mut proposed_current_pixel_change = (drag.position - child_start).along(axis)
731// - size(preceding_ix, flexes.as_slice());
732
733// let flex_changes = |pixel_dx, target_ix, next: isize, flexes: &[f32]| {
734// let flex_change = pixel_dx / drag_bounds.length_along(axis);
735// let current_target_flex = flexes[target_ix] + flex_change;
736// let next_target_flex =
737// flexes[(target_ix as isize + next) as usize] - flex_change;
738// (current_target_flex, next_target_flex)
739// };
740
741// let mut successors = from_fn({
742// let forward = proposed_current_pixel_change > 0.;
743// let mut ix_offset = 0;
744// let len = flexes.len();
745// move || {
746// let result = if forward {
747// (preceding_ix + 1 + ix_offset < len).then(|| preceding_ix + ix_offset)
748// } else {
749// (preceding_ix as isize - ix_offset as isize >= 0)
750// .then(|| preceding_ix - ix_offset)
751// };
752
753// ix_offset += 1;
754
755// result
756// }
757// });
758
759// while proposed_current_pixel_change.abs() > 0. {
760// let Some(current_ix) = successors.next() else {
761// break;
762// };
763
764// let next_target_size = f32::max(
765// size(current_ix + 1, flexes.as_slice()) - proposed_current_pixel_change,
766// min_size,
767// );
768
769// let current_target_size = f32::max(
770// size(current_ix, flexes.as_slice())
771// + size(current_ix + 1, flexes.as_slice())
772// - next_target_size,
773// min_size,
774// );
775
776// let current_pixel_change =
777// current_target_size - size(current_ix, flexes.as_slice());
778
779// let (current_target_flex, next_target_flex) =
780// flex_changes(current_pixel_change, current_ix, 1, flexes.as_slice());
781
782// flexes[current_ix] = current_target_flex;
783// flexes[current_ix + 1] = next_target_flex;
784
785// proposed_current_pixel_change -= current_pixel_change;
786// }
787
788// workspace.schedule_serialize(cx);
789// cx.notify();
790// }
791// }
792// }
793
794// impl Extend<AnyElement<Workspace>> for PaneAxisElement {
795// fn extend<T: IntoIterator<Item = AnyElement<Workspace>>>(&mut self, children: T) {
796// self.children.extend(children);
797// }
798// }
799
800// impl Element<Workspace> for PaneAxisElement {
801// type LayoutState = f32;
802// type PaintState = ();
803
804// fn layout(
805// &mut self,
806// constraint: SizeConstraint,
807// view: &mut Workspace,
808// cx: &mut ViewContext<Workspace>,
809// ) -> (Vector2F, Self::LayoutState) {
810// debug_assert!(self.children.len() == self.flexes.borrow().len());
811
812// let active_pane_magnification =
813// settings::get::<WorkspaceSettings>(cx).active_pane_magnification;
814
815// let mut remaining_flex = 0.;
816
817// if active_pane_magnification != 1. {
818// let active_pane_flex = self
819// .active_pane_ix
820// .map(|_| active_pane_magnification)
821// .unwrap_or(1.);
822// remaining_flex += self.children.len() as f32 - 1. + active_pane_flex;
823// } else {
824// for flex in self.flexes.borrow().iter() {
825// remaining_flex += flex;
826// }
827// }
828
829// let mut cross_axis_max: f32 = 0.0;
830// let mut remaining_space = constraint.max_along(self.axis);
831
832// if remaining_space.is_infinite() {
833// panic!("flex contains flexible children but has an infinite constraint along the flex axis");
834// }
835
836// self.layout_children(
837// active_pane_magnification,
838// constraint,
839// &mut remaining_space,
840// &mut remaining_flex,
841// &mut cross_axis_max,
842// view,
843// cx,
844// );
845
846// let mut size = match self.axis {
847// Axis::Horizontal => vec2f(constraint.max.x() - remaining_space, cross_axis_max),
848// Axis::Vertical => vec2f(cross_axis_max, constraint.max.y() - remaining_space),
849// };
850
851// if constraint.min.x().is_finite() {
852// size.set_x(size.x().max(constraint.min.x()));
853// }
854// if constraint.min.y().is_finite() {
855// size.set_y(size.y().max(constraint.min.y()));
856// }
857
858// if size.x() > constraint.max.x() {
859// size.set_x(constraint.max.x());
860// }
861// if size.y() > constraint.max.y() {
862// size.set_y(constraint.max.y());
863// }
864
865// (size, remaining_space)
866// }
867
868// fn paint(
869// &mut self,
870// bounds: Bounds<Pixels>,
871// visible_bounds: Bounds<Pixels>,
872// remaining_space: &mut Self::LayoutState,
873// view: &mut Workspace,
874// cx: &mut ViewContext<Workspace>,
875// ) -> Self::PaintState {
876// let can_resize = settings::get::<WorkspaceSettings>(cx).active_pane_magnification == 1.;
877// let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
878
879// let overflowing = *remaining_space < 0.;
880// if overflowing {
881// cx.scene().push_layer(Some(visible_bounds));
882// }
883
884// let mut child_origin = bounds.origin();
885
886// let mut bounding_boxes = self.bounding_boxes.borrow_mut();
887// bounding_boxes.clear();
888
889// let mut children_iter = self.children.iter_mut().enumerate().peekable();
890// while let Some((ix, child)) = children_iter.next() {
891// let child_start = child_origin.clone();
892// child.paint(child_origin, visible_bounds, view, cx);
893
894// bounding_boxes.push(Some(Bounds<Pixels>::new(child_origin, child.size())));
895
896// match self.axis {
897// Axis::Horizontal => child_origin += vec2f(child.size().x(), 0.0),
898// Axis::Vertical => child_origin += vec2f(0.0, child.size().y()),
899// }
900
901// if can_resize && children_iter.peek().is_some() {
902// cx.scene().push_stacking_context(None, None);
903
904// let handle_origin = match self.axis {
905// Axis::Horizontal => child_origin - vec2f(HANDLE_HITBOX_SIZE / 2., 0.0),
906// Axis::Vertical => child_origin - vec2f(0.0, HANDLE_HITBOX_SIZE / 2.),
907// };
908
909// let handle_bounds = match self.axis {
910// Axis::Horizontal => Bounds<Pixels>::new(
911// handle_origin,
912// vec2f(HANDLE_HITBOX_SIZE, visible_bounds.height()),
913// ),
914// Axis::Vertical => Bounds<Pixels>::new(
915// handle_origin,
916// vec2f(visible_bounds.width(), HANDLE_HITBOX_SIZE),
917// ),
918// };
919
920// let style = match self.axis {
921// Axis::Horizontal => CursorStyle::ResizeLeftRight,
922// Axis::Vertical => CursorStyle::ResizeUpDown,
923// };
924
925// cx.scene().push_cursor_region(CursorRegion {
926// bounds: handle_bounds,
927// style,
928// });
929
930// enum ResizeHandle {}
931// let mut mouse_region = MouseRegion::new::<ResizeHandle>(
932// cx.view_id(),
933// self.basis + ix,
934// handle_bounds,
935// );
936// mouse_region = mouse_region
937// .on_drag(
938// MouseButton::Left,
939// Self::handle_resize(
940// self.flexes.clone(),
941// self.axis,
942// ix,
943// child_start,
944// visible_bounds.clone(),
945// ),
946// )
947// .on_click(MouseButton::Left, {
948// let flexes = self.flexes.clone();
949// move |e, v: &mut Workspace, cx| {
950// if e.click_count >= 2 {
951// let mut borrow = flexes.borrow_mut();
952// *borrow = vec![1.; borrow.len()];
953// v.schedule_serialize(cx);
954// cx.notify();
955// }
956// }
957// });
958// cx.scene().push_mouse_region(mouse_region);
959
960// cx.scene().pop_stacking_context();
961// }
962// }
963
964// if overflowing {
965// cx.scene().pop_layer();
966// }
967// }
968
969// fn rect_for_text_range(
970// &self,
971// range_utf16: Range<usize>,
972// _: Bounds<Pixels>,
973// _: Bounds<Pixels>,
974// _: &Self::LayoutState,
975// _: &Self::PaintState,
976// view: &Workspace,
977// cx: &ViewContext<Workspace>,
978// ) -> Option<Bounds<Pixels>> {
979// self.children
980// .iter()
981// .find_map(|child| child.rect_for_text_range(range_utf16.clone(), view, cx))
982// }
983
984// fn debug(
985// &self,
986// bounds: Bounds<Pixels>,
987// _: &Self::LayoutState,
988// _: &Self::PaintState,
989// view: &Workspace,
990// cx: &ViewContext<Workspace>,
991// ) -> json::Value {
992// serde_json::json!({
993// "type": "PaneAxis",
994// "bounds": bounds.to_json(),
995// "axis": self.axis.to_json(),
996// "flexes": *self.flexes.borrow(),
997// "children": self.children.iter().map(|child| child.debug(view, cx)).collect::<Vec<json::Value>>()
998// })
999// }
1000// }
1001// }