aboutsummaryrefslogtreecommitdiff
path: root/helix-view
diff options
context:
space:
mode:
Diffstat (limited to 'helix-view')
-rw-r--r--helix-view/src/view.rs89
1 files changed, 60 insertions, 29 deletions
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index ecc8e8be..c09d502d 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -1,4 +1,4 @@
-use crate::{editor::GutterType, graphics::Rect, Document, DocumentId, ViewId};
+use crate::{align_view, editor::GutterType, graphics::Rect, Align, Document, DocumentId, ViewId};
use helix_core::{
pos_at_visual_coords, visual_coords_at_pos, Position, RopeSlice, Selection, Transaction,
};
@@ -170,6 +170,15 @@ impl View {
doc: &Document,
scrolloff: usize,
) -> Option<(usize, usize)> {
+ self.offset_coords_to_in_view_center(doc, scrolloff, false)
+ }
+
+ pub fn offset_coords_to_in_view_center(
+ &self,
+ doc: &Document,
+ scrolloff: usize,
+ centering: bool,
+ ) -> Option<(usize, usize)> {
let cursor = doc
.selection(self.id)
.primary()
@@ -180,47 +189,69 @@ impl View {
let inner_area = self.inner_area(doc);
let last_line = (self.offset.row + inner_area.height as usize).saturating_sub(1);
-
- // - 1 so we have at least one gap in the middle.
- // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
- // as we type
- let scrolloff = scrolloff.min(inner_area.height.saturating_sub(1) as usize / 2);
-
let last_col = self.offset.col + inner_area.width.saturating_sub(1) as usize;
- let row = if line > last_line.saturating_sub(scrolloff) {
- // scroll down
- self.offset.row + line - (last_line.saturating_sub(scrolloff))
- } else if line < self.offset.row + scrolloff {
- // scroll up
- line.saturating_sub(scrolloff)
- } else {
- self.offset.row
+ let new_offset = |scrolloff: usize| {
+ // - 1 so we have at least one gap in the middle.
+ // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
+ // as we type
+ let scrolloff = scrolloff.min(inner_area.height.saturating_sub(1) as usize / 2);
+
+ let row = if line > last_line.saturating_sub(scrolloff) {
+ // scroll down
+ self.offset.row + line - (last_line.saturating_sub(scrolloff))
+ } else if line < self.offset.row + scrolloff {
+ // scroll up
+ line.saturating_sub(scrolloff)
+ } else {
+ self.offset.row
+ };
+
+ let col = if col > last_col.saturating_sub(scrolloff) {
+ // scroll right
+ self.offset.col + col - (last_col.saturating_sub(scrolloff))
+ } else if col < self.offset.col + scrolloff {
+ // scroll left
+ col.saturating_sub(scrolloff)
+ } else {
+ self.offset.col
+ };
+ (row, col)
};
-
- let col = if col > last_col.saturating_sub(scrolloff) {
- // scroll right
- self.offset.col + col - (last_col.saturating_sub(scrolloff))
- } else if col < self.offset.col + scrolloff {
- // scroll left
- col.saturating_sub(scrolloff)
+ let current_offset = (self.offset.row, self.offset.col);
+ if centering {
+ // return None if cursor is out of view
+ let offset = new_offset(0);
+ (offset == current_offset).then(|| {
+ if scrolloff == 0 {
+ offset
+ } else {
+ new_offset(scrolloff)
+ }
+ })
} else {
- self.offset.col
- };
- if row == self.offset.row && col == self.offset.col {
- None
- } else {
- Some((row, col))
+ // return None if cursor is in (view - scrolloff)
+ let offset = new_offset(scrolloff);
+ (offset != current_offset).then(|| offset) // TODO: use 'then_some' when 1.62 <= MSRV
}
}
pub fn ensure_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) {
- if let Some((row, col)) = self.offset_coords_to_in_view(doc, scrolloff) {
+ if let Some((row, col)) = self.offset_coords_to_in_view_center(doc, scrolloff, false) {
self.offset.row = row;
self.offset.col = col;
}
}
+ pub fn ensure_cursor_in_view_center(&mut self, doc: &Document, scrolloff: usize) {
+ if let Some((row, col)) = self.offset_coords_to_in_view_center(doc, scrolloff, true) {
+ self.offset.row = row;
+ self.offset.col = col;
+ } else {
+ align_view(doc, self, Align::Center);
+ }
+ }
+
pub fn is_cursor_in_view(&mut self, doc: &Document, scrolloff: usize) -> bool {
self.offset_coords_to_in_view(doc, scrolloff).is_none()
}