aboutsummaryrefslogtreecommitdiff
path: root/src/app/actions.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-04-10 14:15:23 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-04-10 14:16:25 +0300
commit831bb66c0cda103f79b2418389cd6528c03ade56 (patch)
tree0ae176496c492a035f3eb6fb9f8eab13bd397ca1 /src/app/actions.rs
parente20be7bdae5c46ff922ee442b4fbd5d79c46cf99 (diff)
feat(tabs): add overflow scrolling and drag reorder
Diffstat (limited to 'src/app/actions.rs')
-rw-r--r--src/app/actions.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/app/actions.rs b/src/app/actions.rs
index 97537ef5..da5c8698 100644
--- a/src/app/actions.rs
+++ b/src/app/actions.rs
@@ -126,6 +126,8 @@ impl AppState {
if let Some(ws) = self.workspaces.get_mut(idx) {
ws.switch_tab(ws.active_tab);
}
+ self.tab_scroll_follow_active = true;
+ self.refresh_tab_bar_view();
}
}
@@ -163,6 +165,8 @@ impl AppState {
if let Some(ws) = self.active.and_then(|i| self.workspaces.get_mut(i)) {
ws.switch_tab(idx);
self.mark_session_dirty();
+ self.tab_scroll_follow_active = true;
+ self.refresh_tab_bar_view();
}
}
@@ -215,6 +219,28 @@ impl AppState {
self.ensure_workspace_visible(self.selected);
}
+ pub fn scroll_tabs_left(&mut self) {
+ self.tab_scroll_follow_active = false;
+ self.tab_scroll = self.tab_scroll.saturating_sub(1);
+ self.refresh_tab_bar_view();
+ }
+
+ pub fn scroll_tabs_right(&mut self) {
+ self.tab_scroll_follow_active = false;
+ self.tab_scroll = self.tab_scroll.saturating_add(1);
+ self.refresh_tab_bar_view();
+ }
+
+ pub fn move_tab(&mut self, source_idx: usize, insert_idx: usize) {
+ if let Some(ws) = self.active.and_then(|i| self.workspaces.get_mut(i)) {
+ if ws.move_tab(source_idx, insert_idx) {
+ self.mark_session_dirty();
+ self.tab_scroll_follow_active = true;
+ self.refresh_tab_bar_view();
+ }
+ }
+ }
+
pub fn next_tab(&mut self) {
if let Some(ws) = self.active.and_then(|i| self.workspaces.get(i)) {
if !ws.tabs.is_empty() {
@@ -249,6 +275,8 @@ impl AppState {
self.active = None;
self.selected = 0;
self.workspace_scroll = 0;
+ self.tab_scroll = 0;
+ self.tab_scroll_follow_active = true;
} else {
if self.selected >= self.workspaces.len() {
self.selected = self.workspaces.len() - 1;
@@ -258,8 +286,34 @@ impl AppState {
.workspace_scroll
.min(self.workspaces.len().saturating_sub(1));
self.ensure_workspace_visible(self.selected);
+ self.tab_scroll_follow_active = true;
+ self.refresh_tab_bar_view();
}
}
+
+ fn refresh_tab_bar_view(&mut self) {
+ let area = self.view.tab_bar_rect;
+ let Some(ws) = self.active.and_then(|idx| self.workspaces.get(idx)) else {
+ self.tab_scroll = 0;
+ self.view.tab_hit_areas.clear();
+ self.view.tab_scroll_left_hit_area = ratatui::layout::Rect::default();
+ self.view.tab_scroll_right_hit_area = ratatui::layout::Rect::default();
+ self.view.new_tab_hit_area = ratatui::layout::Rect::default();
+ return;
+ };
+
+ let layout = crate::ui::compute_tab_bar_view(
+ ws,
+ area,
+ self.tab_scroll,
+ self.tab_scroll_follow_active,
+ );
+ self.tab_scroll = layout.scroll;
+ self.view.tab_hit_areas = layout.tab_hit_areas;
+ self.view.tab_scroll_left_hit_area = layout.scroll_left_hit_area;
+ self.view.tab_scroll_right_hit_area = layout.scroll_right_hit_area;
+ self.view.new_tab_hit_area = layout.new_tab_hit_area;
+ }
}
// ---------------------------------------------------------------------------
@@ -352,6 +406,8 @@ impl AppState {
}
if let Some(ws) = self.active.and_then(|i| self.workspaces.get_mut(i)) {
ws.close_active_tab();
+ self.tab_scroll_follow_active = true;
+ self.refresh_tab_bar_view();
}
}
}