fresh/app/
view_actions.rs1use crate::app::window::Window;
9use crate::model::event::LeafId;
10use crate::state::ViewMode;
11use rust_i18n::t;
12
13impl Window {
14 pub fn handle_toggle_page_view(&mut self) {
16 let (mgr, _) = self
17 .buffers
18 .splits()
19 .expect("active window must have a populated split layout");
20 let active_split = mgr.active_split();
21 let active_buffer = mgr
22 .get_buffer_id(active_split.into())
23 .unwrap_or(crate::model::event::BufferId(0));
24 let default_wrap = self.resolve_line_wrap_for_buffer(active_buffer);
25 let default_line_numbers = self.config().editor.line_numbers;
26 let page_width = self
27 .buffers
28 .get(&active_buffer)
29 .and_then(|s| self.config().languages.get(&s.language))
30 .and_then(|lc| lc.page_width)
31 .or(self.config().editor.page_width);
32
33 let view_mode = {
34 let (_, vs_map) = self
35 .buffers
36 .splits()
37 .expect("active window must have a populated split layout");
38 let current = vs_map
39 .get(&active_split)
40 .map(|vs| vs.view_mode.clone())
41 .unwrap_or(ViewMode::Source);
42 match current {
43 ViewMode::PageView => ViewMode::Source,
44 _ => ViewMode::PageView,
45 }
46 };
47
48 if let Some(vs) = self
50 .split_view_states_mut()
51 .expect("active window must have a populated split layout")
52 .get_mut(&active_split)
53 {
54 vs.view_mode = view_mode.clone();
55 vs.viewport.line_wrap_enabled = match view_mode {
59 ViewMode::PageView => false,
60 ViewMode::Source => vs.line_wrap_override.unwrap_or(default_wrap),
63 };
64 match view_mode {
65 ViewMode::PageView => {
66 vs.show_line_numbers = false;
67 if let Some(width) = page_width {
69 vs.compose_width = Some(width as u16);
70 }
71 }
72 ViewMode::Source => {
73 vs.compose_width = None;
75 vs.view_transform = None;
76 vs.show_line_numbers = vs.line_numbers_override.unwrap_or(default_line_numbers);
78 }
79 }
80 }
81
82 let mode_label = match view_mode {
83 ViewMode::PageView => t!("view.page_view").to_string(),
84 ViewMode::Source => "Source".to_string(),
85 };
86 self.set_status_message(t!("view.mode", mode = mode_label).to_string());
87 }
88
89 pub(crate) fn animate_tab_switch(&mut self, split_id: LeafId, direction: i32) {
100 if direction == 0 {
101 return;
102 }
103 if !self.config().editor.animations {
104 return;
105 }
106 let Some(area) = self.split_or_group_content_rect(split_id) else {
107 return;
108 };
109 if area.width == 0 || area.height == 0 {
110 return;
111 }
112 let from = if direction > 0 {
113 crate::view::animation::Edge::Right
114 } else {
115 crate::view::animation::Edge::Left
116 };
117 self.animations.start(
118 area,
119 crate::view::animation::AnimationKind::SlideIn {
120 from,
121 duration: std::time::Duration::from_millis(260),
122 delay: std::time::Duration::ZERO,
123 },
124 );
125 }
126
127 fn split_or_group_content_rect(&self, split_id: LeafId) -> Option<ratatui::layout::Rect> {
140 if let Some(rect) = self
141 .layout_cache
142 .split_areas
143 .iter()
144 .find(|(sid, _, _, _, _, _)| *sid == split_id)
145 .map(|(_, _, content_rect, _, _, _)| *content_rect)
146 {
147 return Some(rect);
148 }
149
150 let (_, vs_map) = self
154 .buffers
155 .splits()
156 .expect("active window must have a populated split layout");
157 let group_leaf = vs_map.get(&split_id).and_then(|vs| vs.active_group_tab)?;
158 let subtree = self.grouped_subtrees.get(&group_leaf)?;
159
160 let mut inner_leaves: Vec<LeafId> = Vec::new();
161 collect_leaf_ids(subtree, &mut inner_leaves);
162
163 let mut union: Option<ratatui::layout::Rect> = None;
164 for (sid, _, content, _, _, _) in &self.layout_cache.split_areas {
165 if !inner_leaves.contains(sid) {
166 continue;
167 }
168 union = Some(match union {
169 None => *content,
170 Some(prev) => rect_union(prev, *content),
171 });
172 }
173 union
174 }
175}
176
177fn collect_leaf_ids(node: &crate::view::split::SplitNode, out: &mut Vec<LeafId>) {
179 use crate::view::split::SplitNode;
180 match node {
181 SplitNode::Leaf { split_id, .. } => out.push(*split_id),
182 SplitNode::Split { first, second, .. } => {
183 collect_leaf_ids(first, out);
184 collect_leaf_ids(second, out);
185 }
186 SplitNode::Grouped { layout, .. } => collect_leaf_ids(layout, out),
187 }
188}
189
190fn rect_union(a: ratatui::layout::Rect, b: ratatui::layout::Rect) -> ratatui::layout::Rect {
191 let x = a.x.min(b.x);
192 let y = a.y.min(b.y);
193 let right = a.x.saturating_add(a.width).max(b.x.saturating_add(b.width));
194 let bottom =
195 a.y.saturating_add(a.height)
196 .max(b.y.saturating_add(b.height));
197 ratatui::layout::Rect::new(x, y, right.saturating_sub(x), bottom.saturating_sub(y))
198}