1
- use crate :: { editor:: GutterType , graphics:: Rect , Document , DocumentId , ViewId } ;
1
+ use crate :: { align_view , editor:: GutterType , graphics:: Rect , Align , Document , DocumentId , ViewId } ;
2
2
use helix_core:: {
3
3
pos_at_visual_coords, visual_coords_at_pos, Position , RopeSlice , Selection , Transaction ,
4
4
} ;
@@ -169,6 +169,15 @@ impl View {
169
169
& self ,
170
170
doc : & Document ,
171
171
scrolloff : usize ,
172
+ ) -> Option < ( usize , usize ) > {
173
+ self . offset_coords_to_in_view_center ( doc, scrolloff, false )
174
+ }
175
+
176
+ pub fn offset_coords_to_in_view_center (
177
+ & self ,
178
+ doc : & Document ,
179
+ scrolloff : usize ,
180
+ centering : bool ,
172
181
) -> Option < ( usize , usize ) > {
173
182
let cursor = doc
174
183
. selection ( self . id )
@@ -180,47 +189,69 @@ impl View {
180
189
181
190
let inner_area = self . inner_area ( doc) ;
182
191
let last_line = ( self . offset . row + inner_area. height as usize ) . saturating_sub ( 1 ) ;
183
-
184
- // - 1 so we have at least one gap in the middle.
185
- // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
186
- // as we type
187
- let scrolloff = scrolloff. min ( inner_area. height . saturating_sub ( 1 ) as usize / 2 ) ;
188
-
189
192
let last_col = self . offset . col + inner_area. width . saturating_sub ( 1 ) as usize ;
190
193
191
- let row = if line > last_line. saturating_sub ( scrolloff) {
192
- // scroll down
193
- self . offset . row + line - ( last_line. saturating_sub ( scrolloff) )
194
- } else if line < self . offset . row + scrolloff {
195
- // scroll up
196
- line. saturating_sub ( scrolloff)
197
- } else {
198
- self . offset . row
194
+ let new_offset = |scrolloff : usize | {
195
+ // - 1 so we have at least one gap in the middle.
196
+ // a height of 6 with padding of 3 on each side will keep shifting the view back and forth
197
+ // as we type
198
+ let scrolloff = scrolloff. min ( inner_area. height . saturating_sub ( 1 ) as usize / 2 ) ;
199
+
200
+ let row = if line > last_line. saturating_sub ( scrolloff) {
201
+ // scroll down
202
+ self . offset . row + line - ( last_line. saturating_sub ( scrolloff) )
203
+ } else if line < self . offset . row + scrolloff {
204
+ // scroll up
205
+ line. saturating_sub ( scrolloff)
206
+ } else {
207
+ self . offset . row
208
+ } ;
209
+
210
+ let col = if col > last_col. saturating_sub ( scrolloff) {
211
+ // scroll right
212
+ self . offset . col + col - ( last_col. saturating_sub ( scrolloff) )
213
+ } else if col < self . offset . col + scrolloff {
214
+ // scroll left
215
+ col. saturating_sub ( scrolloff)
216
+ } else {
217
+ self . offset . col
218
+ } ;
219
+ ( row, col)
199
220
} ;
200
-
201
- let col = if col > last_col. saturating_sub ( scrolloff) {
202
- // scroll right
203
- self . offset . col + col - ( last_col. saturating_sub ( scrolloff) )
204
- } else if col < self . offset . col + scrolloff {
205
- // scroll left
206
- col. saturating_sub ( scrolloff)
221
+ let current_offset = ( self . offset . row , self . offset . col ) ;
222
+ if centering {
223
+ // return None if cursor is out of view
224
+ let offset = new_offset ( 0 ) ;
225
+ ( offset == current_offset) . then ( || {
226
+ if scrolloff == 0 {
227
+ offset
228
+ } else {
229
+ new_offset ( scrolloff)
230
+ }
231
+ } )
207
232
} else {
208
- self . offset . col
209
- } ;
210
- if row == self . offset . row && col == self . offset . col {
211
- None
212
- } else {
213
- Some ( ( row, col) )
233
+ // return None if cursor is in (view - scrolloff)
234
+ let offset = new_offset ( scrolloff) ;
235
+ ( offset != current_offset) . then ( || offset) // TODO: use 'then_some' when 1.62 <= MSRV
214
236
}
215
237
}
216
238
217
239
pub fn ensure_cursor_in_view ( & mut self , doc : & Document , scrolloff : usize ) {
218
- if let Some ( ( row, col) ) = self . offset_coords_to_in_view ( doc, scrolloff) {
240
+ if let Some ( ( row, col) ) = self . offset_coords_to_in_view_center ( doc, scrolloff, false ) {
219
241
self . offset . row = row;
220
242
self . offset . col = col;
221
243
}
222
244
}
223
245
246
+ pub fn ensure_cursor_in_view_center ( & mut self , doc : & Document , scrolloff : usize ) {
247
+ if let Some ( ( row, col) ) = self . offset_coords_to_in_view_center ( doc, scrolloff, true ) {
248
+ self . offset . row = row;
249
+ self . offset . col = col;
250
+ } else {
251
+ align_view ( doc, self , Align :: Center ) ;
252
+ }
253
+ }
254
+
224
255
pub fn is_cursor_in_view ( & mut self , doc : & Document , scrolloff : usize ) -> bool {
225
256
self . offset_coords_to_in_view ( doc, scrolloff) . is_none ( )
226
257
}
0 commit comments