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