1use gpui::{actions, geometry::vector::Vector2F, AppContext, Axis, ViewContext};
2use language::Bias;
3
4use crate::{Editor, EditorMode};
5
6use super::{autoscroll::Autoscroll, scroll_amount::ScrollAmount, ScrollAnchor};
7
8actions!(
9 editor,
10 [
11 LineDown,
12 LineUp,
13 HalfPageDown,
14 HalfPageUp,
15 PageDown,
16 PageUp,
17 NextScreen,
18 ScrollCursorTop,
19 ScrollCursorCenter,
20 ScrollCursorBottom,
21 ]
22);
23
24pub fn init(cx: &mut AppContext) {
25 cx.add_action(Editor::next_screen);
26 cx.add_action(Editor::scroll_cursor_top);
27 cx.add_action(Editor::scroll_cursor_center);
28 cx.add_action(Editor::scroll_cursor_bottom);
29 cx.add_action(|this: &mut Editor, _: &LineDown, cx| {
30 this.scroll_screen(&ScrollAmount::Line(1.), cx)
31 });
32 cx.add_action(|this: &mut Editor, _: &LineUp, cx| {
33 this.scroll_screen(&ScrollAmount::Line(-1.), cx)
34 });
35 cx.add_action(|this: &mut Editor, _: &HalfPageDown, cx| {
36 this.scroll_screen(&ScrollAmount::Page(0.5), cx)
37 });
38 cx.add_action(|this: &mut Editor, _: &HalfPageUp, cx| {
39 this.scroll_screen(&ScrollAmount::Page(-0.5), cx)
40 });
41 cx.add_action(|this: &mut Editor, _: &PageDown, cx| {
42 this.scroll_screen(&ScrollAmount::Page(1.), cx)
43 });
44 cx.add_action(|this: &mut Editor, _: &PageUp, cx| {
45 this.scroll_screen(&ScrollAmount::Page(-1.), cx)
46 });
47}
48
49impl Editor {
50 pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) -> Option<()> {
51 if self.take_rename(true, cx).is_some() {
52 return None;
53 }
54
55 if self.mouse_context_menu.read(cx).visible() {
56 return None;
57 }
58
59 if matches!(self.mode, EditorMode::SingleLine) {
60 cx.propagate_action();
61 return None;
62 }
63 self.request_autoscroll(Autoscroll::Next, cx);
64 Some(())
65 }
66
67 pub fn scroll(
68 &mut self,
69 scroll_position: Vector2F,
70 axis: Option<Axis>,
71 cx: &mut ViewContext<Self>,
72 ) {
73 self.scroll_manager.update_ongoing_scroll(axis);
74 self.set_scroll_position(scroll_position, cx);
75 }
76
77 fn scroll_cursor_top(editor: &mut Editor, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) {
78 let snapshot = editor.snapshot(cx).display_snapshot;
79 let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
80
81 let mut new_screen_top = editor.selections.newest_display(cx).head();
82 *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(scroll_margin_rows);
83 *new_screen_top.column_mut() = 0;
84 let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
85 let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
86
87 editor.set_scroll_anchor(
88 ScrollAnchor {
89 anchor: new_anchor,
90 offset: Default::default(),
91 },
92 cx,
93 )
94 }
95
96 fn scroll_cursor_center(
97 editor: &mut Editor,
98 _: &ScrollCursorCenter,
99 cx: &mut ViewContext<Editor>,
100 ) {
101 let snapshot = editor.snapshot(cx).display_snapshot;
102 let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
103 visible_rows as u32
104 } else {
105 return;
106 };
107
108 let mut new_screen_top = editor.selections.newest_display(cx).head();
109 *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(visible_rows / 2);
110 *new_screen_top.column_mut() = 0;
111 let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
112 let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
113
114 editor.set_scroll_anchor(
115 ScrollAnchor {
116 anchor: new_anchor,
117 offset: Default::default(),
118 },
119 cx,
120 )
121 }
122
123 fn scroll_cursor_bottom(
124 editor: &mut Editor,
125 _: &ScrollCursorBottom,
126 cx: &mut ViewContext<Editor>,
127 ) {
128 let snapshot = editor.snapshot(cx).display_snapshot;
129 let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
130 let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
131 visible_rows as u32
132 } else {
133 return;
134 };
135
136 let mut new_screen_top = editor.selections.newest_display(cx).head();
137 *new_screen_top.row_mut() = new_screen_top
138 .row()
139 .saturating_sub(visible_rows.saturating_sub(scroll_margin_rows));
140 *new_screen_top.column_mut() = 0;
141 let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
142 let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
143
144 editor.set_scroll_anchor(
145 ScrollAnchor {
146 anchor: new_anchor,
147 offset: Default::default(),
148 },
149 cx,
150 )
151 }
152}