Add split layout axis commands
This commit is contained in:
@@ -73,18 +73,45 @@ impl ElyShell {
|
|||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.bg(rgb(colors::CANVAS));
|
.bg(rgb(colors::CANVAS));
|
||||||
|
|
||||||
let body = match layout.axis() {
|
match layout.axis() {
|
||||||
SplitAxis::Vertical => body.flex().flex_col(),
|
SplitAxis::Horizontal => body
|
||||||
SplitAxis::Horizontal | SplitAxis::Grid => body.flex(),
|
.flex()
|
||||||
};
|
.children(
|
||||||
|
panes
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, tab)| self.render_split_pane(index, tab, snapshot, cx)),
|
||||||
|
)
|
||||||
|
.into_any_element(),
|
||||||
|
SplitAxis::Vertical => body
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.children(
|
||||||
|
panes
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, tab)| self.render_split_pane(index, tab, snapshot, cx)),
|
||||||
|
)
|
||||||
|
.into_any_element(),
|
||||||
|
SplitAxis::Grid => self.render_split_grid(body, panes, snapshot, cx).into_any_element(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
body.children(
|
fn render_split_grid(
|
||||||
panes
|
&mut self,
|
||||||
.into_iter()
|
body: gpui::Div,
|
||||||
.enumerate()
|
panes: Vec<&BrowserTab>,
|
||||||
.map(|(index, tab)| self.render_split_pane(index, tab, snapshot, cx)),
|
snapshot: &BrowserSnapshot,
|
||||||
)
|
cx: &mut Context<Self>,
|
||||||
.into_any_element()
|
) -> gpui::Div {
|
||||||
|
body.flex().flex_col().children(panes.chunks(2).enumerate().map(|(row_index, row)| {
|
||||||
|
div().flex().flex_1().min_h(px(180.0)).gap_3().children(row.iter().enumerate().map(
|
||||||
|
|(column_index, tab)| {
|
||||||
|
let pane_index = row_index * 2 + column_index;
|
||||||
|
self.render_split_pane(pane_index, tab, snapshot, cx)
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_split_pane(
|
fn render_split_pane(
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use ely_domain::{ArchivePolicy, CommandIntent, CommandScope, ProfileId, ProfileKind, SpaceId};
|
use ely_domain::{
|
||||||
|
ArchivePolicy, CommandIntent, CommandScope, ProfileId, ProfileKind, SpaceId, SplitAxis,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
CoreError,
|
CoreError,
|
||||||
@@ -162,6 +164,15 @@ impl BrowserCore {
|
|||||||
self.split_active_tab_right()?;
|
self.split_active_tab_right()?;
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
"split-horizontal" | "split horizontal" => {
|
||||||
|
Ok(self.set_active_split_axis(SplitAxis::Horizontal)?.is_some())
|
||||||
|
}
|
||||||
|
"split-vertical" | "split vertical" => {
|
||||||
|
Ok(self.set_active_split_axis(SplitAxis::Vertical)?.is_some())
|
||||||
|
}
|
||||||
|
"split-grid" | "split grid" => {
|
||||||
|
Ok(self.set_active_split_axis(SplitAxis::Grid)?.is_some())
|
||||||
|
}
|
||||||
"save-split-view" | "save split view" => Ok(self.save_active_split_view()?.is_some()),
|
"save-split-view" | "save split view" => Ok(self.save_active_split_view()?.is_some()),
|
||||||
"split-tab-group" | "split tab group" | "tab-group-to-split" | "tab group to split" => {
|
"split-tab-group" | "split tab group" | "tab-group-to-split" | "tab group to split" => {
|
||||||
Ok(self.split_active_tab_group()?.is_some())
|
Ok(self.split_active_tab_group()?.is_some())
|
||||||
|
|||||||
@@ -68,6 +68,20 @@ impl BrowserCore {
|
|||||||
Ok(Some(split_id))
|
Ok(Some(split_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_active_split_axis(&mut self, axis: SplitAxis) -> Result<Option<SplitId>, CoreError> {
|
||||||
|
let Some(split_id) = self.active_tab()?.split_id().cloned() else {
|
||||||
|
return Ok(None);
|
||||||
|
};
|
||||||
|
let layout = self
|
||||||
|
.split_layouts
|
||||||
|
.iter_mut()
|
||||||
|
.find(|layout| layout.id() == &split_id)
|
||||||
|
.ok_or_else(|| CoreError::SplitNotFound { id: split_id.clone() })?;
|
||||||
|
|
||||||
|
layout.set_axis(axis);
|
||||||
|
Ok(Some(split_id))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn split_active_tab_right(&mut self) -> Result<SplitId, CoreError> {
|
pub fn split_active_tab_right(&mut self) -> Result<SplitId, CoreError> {
|
||||||
let active_index = self.active_tab_index()?;
|
let active_index = self.active_tab_index()?;
|
||||||
let active_tab_id = self.tabs[active_index].id().clone();
|
let active_tab_id = self.tabs[active_index].id().clone();
|
||||||
|
|||||||
@@ -75,6 +75,77 @@ fn save_split_view_command_preserves_query_without_active_split() -> Result<(),
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_axis_commands_update_active_layout() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.split_active_tab_right()?;
|
||||||
|
|
||||||
|
core.set_command_query(">split-vertical");
|
||||||
|
let vertical_intent = core.submit_command()?;
|
||||||
|
let vertical_snapshot = core.snapshot()?;
|
||||||
|
let vertical_layout = vertical_snapshot.split_layouts.first().ok_or("missing split layout")?;
|
||||||
|
|
||||||
|
assert_eq!(vertical_intent, Some(CommandIntent::Command("split-vertical".to_string())));
|
||||||
|
assert_eq!(vertical_layout.axis(), &SplitAxis::Vertical);
|
||||||
|
assert_eq!(vertical_snapshot.command_query, "");
|
||||||
|
|
||||||
|
core.set_command_query(">split-grid");
|
||||||
|
let grid_intent = core.submit_command()?;
|
||||||
|
let grid_snapshot = core.snapshot()?;
|
||||||
|
let grid_layout = grid_snapshot.split_layouts.first().ok_or("missing split layout")?;
|
||||||
|
|
||||||
|
assert_eq!(grid_intent, Some(CommandIntent::Command("split-grid".to_string())));
|
||||||
|
assert_eq!(grid_layout.axis(), &SplitAxis::Grid);
|
||||||
|
assert_eq!(grid_snapshot.command_query, "");
|
||||||
|
|
||||||
|
core.set_command_query(">split-horizontal");
|
||||||
|
let horizontal_intent = core.submit_command()?;
|
||||||
|
let horizontal_snapshot = core.snapshot()?;
|
||||||
|
let horizontal_layout =
|
||||||
|
horizontal_snapshot.split_layouts.first().ok_or("missing split layout")?;
|
||||||
|
|
||||||
|
assert_eq!(horizontal_intent, Some(CommandIntent::Command("split-horizontal".to_string())));
|
||||||
|
assert_eq!(horizontal_layout.axis(), &SplitAxis::Horizontal);
|
||||||
|
assert_eq!(horizontal_snapshot.command_query, "");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_axis_command_preserves_query_without_active_split() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
let active_tab_id = core.active_tab()?.id().clone();
|
||||||
|
|
||||||
|
core.set_command_query(">split-grid");
|
||||||
|
let intent = core.submit_command()?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
|
||||||
|
assert_eq!(intent, Some(CommandIntent::Command("split-grid".to_string())));
|
||||||
|
assert_eq!(snapshot.active_tab_id, active_tab_id);
|
||||||
|
assert!(snapshot.split_layouts.is_empty());
|
||||||
|
assert_eq!(snapshot.command_query, ">split-grid");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn split_grid_command_keeps_four_pane_layout() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
core.split_active_tab_right()?;
|
||||||
|
core.split_active_tab_right()?;
|
||||||
|
core.split_active_tab_right()?;
|
||||||
|
|
||||||
|
core.set_command_query(">split-grid");
|
||||||
|
let intent = core.submit_command()?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
let layout = snapshot.split_layouts.first().ok_or("missing split layout")?;
|
||||||
|
|
||||||
|
assert_eq!(intent, Some(CommandIntent::Command("split-grid".to_string())));
|
||||||
|
assert_eq!(layout.axis(), &SplitAxis::Grid);
|
||||||
|
assert_eq!(layout.pane_count(), 4);
|
||||||
|
assert_eq!(snapshot.tabs.len(), 4);
|
||||||
|
assert_eq!(snapshot.command_query, "");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn close_active_tab_archives_saved_split_view() -> Result<(), Box<dyn Error>> {
|
fn close_active_tab_archives_saved_split_view() -> Result<(), Box<dyn Error>> {
|
||||||
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
|||||||
@@ -57,6 +57,10 @@ impl SplitLayout {
|
|||||||
&self.axis
|
&self.axis
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_axis(&mut self, axis: SplitAxis) {
|
||||||
|
self.axis = axis;
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn panes(&self) -> &[SplitPane] {
|
pub fn panes(&self) -> &[SplitPane] {
|
||||||
&self.panes
|
&self.panes
|
||||||
|
|||||||
Reference in New Issue
Block a user