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 => default_wrap,
61 };
62 match view_mode {
63 ViewMode::PageView => {
64 vs.show_line_numbers = false;
65 if let Some(width) = page_width {
67 vs.compose_width = Some(width as u16);
68 }
69 }
70 ViewMode::Source => {
71 vs.compose_width = None;
73 vs.view_transform = None;
74 vs.show_line_numbers = default_line_numbers;
75 }
76 }
77 }
78
79 let mode_label = match view_mode {
80 ViewMode::PageView => t!("view.page_view").to_string(),
81 ViewMode::Source => "Source".to_string(),
82 };
83 self.set_status_message(t!("view.mode", mode = mode_label).to_string());
84 }
85
86 pub(crate) fn animate_tab_switch(&mut self, split_id: LeafId, direction: i32) {
97 if direction == 0 {
98 return;
99 }
100 if !self.config().editor.animations {
101 return;
102 }
103 let Some(area) = self.split_or_group_content_rect(split_id) else {
104 return;
105 };
106 if area.width == 0 || area.height == 0 {
107 return;
108 }
109 let from = if direction > 0 {
110 crate::view::animation::Edge::Right
111 } else {
112 crate::view::animation::Edge::Left
113 };
114 self.animations.start(
115 area,
116 crate::view::animation::AnimationKind::SlideIn {
117 from,
118 duration: std::time::Duration::from_millis(260),
119 delay: std::time::Duration::ZERO,
120 },
121 );
122 }
123
124 fn split_or_group_content_rect(&self, split_id: LeafId) -> Option<ratatui::layout::Rect> {
137 if let Some(rect) = self
138 .layout_cache
139 .split_areas
140 .iter()
141 .find(|(sid, _, _, _, _, _)| *sid == split_id)
142 .map(|(_, _, content_rect, _, _, _)| *content_rect)
143 {
144 return Some(rect);
145 }
146
147 let (_, vs_map) = self
151 .buffers
152 .splits()
153 .expect("active window must have a populated split layout");
154 let group_leaf = vs_map.get(&split_id).and_then(|vs| vs.active_group_tab)?;
155 let subtree = self.grouped_subtrees.get(&group_leaf)?;
156
157 let mut inner_leaves: Vec<LeafId> = Vec::new();
158 collect_leaf_ids(subtree, &mut inner_leaves);
159
160 let mut union: Option<ratatui::layout::Rect> = None;
161 for (sid, _, content, _, _, _) in &self.layout_cache.split_areas {
162 if !inner_leaves.contains(sid) {
163 continue;
164 }
165 union = Some(match union {
166 None => *content,
167 Some(prev) => rect_union(prev, *content),
168 });
169 }
170 union
171 }
172}
173
174fn collect_leaf_ids(node: &crate::view::split::SplitNode, out: &mut Vec<LeafId>) {
176 use crate::view::split::SplitNode;
177 match node {
178 SplitNode::Leaf { split_id, .. } => out.push(*split_id),
179 SplitNode::Split { first, second, .. } => {
180 collect_leaf_ids(first, out);
181 collect_leaf_ids(second, out);
182 }
183 SplitNode::Grouped { layout, .. } => collect_leaf_ids(layout, out),
184 }
185}
186
187fn rect_union(a: ratatui::layout::Rect, b: ratatui::layout::Rect) -> ratatui::layout::Rect {
188 let x = a.x.min(b.x);
189 let y = a.y.min(b.y);
190 let right = a.x.saturating_add(a.width).max(b.x.saturating_add(b.width));
191 let bottom =
192 a.y.saturating_add(a.height)
193 .max(b.y.saturating_add(b.height));
194 ratatui::layout::Rect::new(x, y, right.saturating_sub(x), bottom.saturating_sub(y))
195}