@ -128,7 +128,6 @@ pub struct ViewPosition {
#[ derive(Clone) ]
#[ derive(Clone) ]
pub struct View {
pub struct View {
pub id : ViewId ,
pub id : ViewId ,
pub offset : ViewPosition ,
pub area : Rect ,
pub area : Rect ,
pub doc : DocumentId ,
pub doc : DocumentId ,
pub jumps : JumpList ,
pub jumps : JumpList ,
@ -173,11 +172,6 @@ impl View {
Self {
Self {
id : ViewId ::default ( ) ,
id : ViewId ::default ( ) ,
doc ,
doc ,
offset : ViewPosition {
anchor : 0 ,
horizontal_offset : 0 ,
vertical_offset : 0 ,
} ,
area : Rect ::default ( ) , // will get calculated upon inserting into tree
area : Rect ::default ( ) , // will get calculated upon inserting into tree
jumps : JumpList ::new ( ( doc , Selection ::point ( 0 ) ) ) , // TODO: use actual sel
jumps : JumpList ::new ( ( doc , Selection ::point ( 0 ) ) ) , // TODO: use actual sel
docs_access_history : Vec ::new ( ) ,
docs_access_history : Vec ::new ( ) ,
@ -240,9 +234,10 @@ impl View {
doc : & Document ,
doc : & Document ,
scrolloff : usize ,
scrolloff : usize ,
) -> Option < ViewPosition > {
) -> Option < ViewPosition > {
let view_offset = doc . get_view_offset ( self . id ) ? ;
let doc_text = doc . text ( ) . slice ( .. ) ;
let doc_text = doc . text ( ) . slice ( .. ) ;
let viewport = self . inner_area ( doc ) ;
let viewport = self . inner_area ( doc ) ;
let vertical_viewport_end = self . offset. vertical_offset + viewport . height as usize ;
let vertical_viewport_end = view_ offset. vertical_offset + viewport . height as usize ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
@ -256,7 +251,7 @@ impl View {
} ;
} ;
let cursor = doc . selection ( self . id ) . primary ( ) . cursor ( doc_text ) ;
let cursor = doc . selection ( self . id ) . primary ( ) . cursor ( doc_text ) ;
let mut offset = self . offset;
let mut offset = view_ offset;
let off = visual_offset_from_anchor (
let off = visual_offset_from_anchor (
doc_text ,
doc_text ,
offset . anchor ,
offset . anchor ,
@ -321,22 +316,22 @@ impl View {
}
}
// if we are not centering return None if view position is unchanged
// if we are not centering return None if view position is unchanged
if ! CENTERING & & offset = = self . offset {
if ! CENTERING & & offset = = view_ offset {
return None ;
return None ;
}
}
Some ( offset )
Some ( offset )
}
}
pub fn ensure_cursor_in_view ( & mut self , doc : & Document, scrolloff : usize ) {
pub fn ensure_cursor_in_view ( & self , doc : & mut Document, scrolloff : usize ) {
if let Some ( offset ) = self . offset_coords_to_in_view_center ::< false > ( doc , scrolloff ) {
if let Some ( offset ) = self . offset_coords_to_in_view_center ::< false > ( doc , scrolloff ) {
self . offset = offset ;
doc . set_view_offset ( self . id , offset ) ;
}
}
}
}
pub fn ensure_cursor_in_view_center ( & mut self , doc : & Document, scrolloff : usize ) {
pub fn ensure_cursor_in_view_center ( & self , doc : & mut Document, scrolloff : usize ) {
if let Some ( offset ) = self . offset_coords_to_in_view_center ::< true > ( doc , scrolloff ) {
if let Some ( offset ) = self . offset_coords_to_in_view_center ::< true > ( doc , scrolloff ) {
self . offset = offset ;
doc . set_view_offset ( self . id , offset ) ;
} else {
} else {
align_view ( doc , self , Align ::Center ) ;
align_view ( doc , self , Align ::Center ) ;
}
}
@ -354,7 +349,7 @@ impl View {
#[ inline ]
#[ inline ]
pub fn estimate_last_doc_line ( & self , doc : & Document ) -> usize {
pub fn estimate_last_doc_line ( & self , doc : & Document ) -> usize {
let doc_text = doc . text ( ) . slice ( .. ) ;
let doc_text = doc . text ( ) . slice ( .. ) ;
let line = doc_text . char_to_line ( self . offset . anchor . min ( doc_text . len_chars ( ) ) ) ;
let line = doc_text . char_to_line ( doc . view_offset ( self . id ) . anchor . min ( doc_text . len_chars ( ) ) ) ;
// Saturating subs to make it inclusive zero indexing.
// Saturating subs to make it inclusive zero indexing.
( line + self . inner_height ( ) )
( line + self . inner_height ( ) )
. min ( doc_text . len_lines ( ) )
. min ( doc_text . len_lines ( ) )
@ -368,9 +363,10 @@ impl View {
let viewport = self . inner_area ( doc ) ;
let viewport = self . inner_area ( doc ) ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
let view_offset = doc . view_offset ( self . id ) ;
// last visual line in view is trivial to compute
// last visual line in view is trivial to compute
let visual_height = self . offset . vertical_offset + viewport . height as usize ;
let visual_height = doc . view_offset ( self . id ) . vertical_offset + viewport . height as usize ;
// fast path when the EOF is not visible on the screen,
// fast path when the EOF is not visible on the screen,
if self . estimate_last_doc_line ( doc ) < doc_text . len_lines ( ) - 1 {
if self . estimate_last_doc_line ( doc ) < doc_text . len_lines ( ) - 1 {
@ -380,7 +376,7 @@ impl View {
// translate to document line
// translate to document line
let pos = visual_offset_from_anchor (
let pos = visual_offset_from_anchor (
doc_text ,
doc_text ,
self . offset. anchor ,
view_ offset. anchor ,
usize ::MAX ,
usize ::MAX ,
& text_fmt ,
& text_fmt ,
& annotations ,
& annotations ,
@ -388,7 +384,7 @@ impl View {
) ;
) ;
match pos {
match pos {
Ok ( ( Position { row , .. } , _ ) ) = > row . saturating_sub ( self . offset. vertical_offset ) ,
Ok ( ( Position { row , .. } , _ ) ) = > row . saturating_sub ( view_ offset. vertical_offset ) ,
Err ( PosAfterMaxRow ) = > visual_height . saturating_sub ( 1 ) ,
Err ( PosAfterMaxRow ) = > visual_height . saturating_sub ( 1 ) ,
Err ( PosBeforeAnchorRow ) = > 0 ,
Err ( PosBeforeAnchorRow ) = > 0 ,
}
}
@ -403,13 +399,15 @@ impl View {
text : RopeSlice ,
text : RopeSlice ,
pos : usize ,
pos : usize ,
) -> Option < Position > {
) -> Option < Position > {
let view_offset = doc . view_offset ( self . id ) ;
let viewport = self . inner_area ( doc ) ;
let viewport = self . inner_area ( doc ) ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let text_fmt = doc . text_format ( viewport . width , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
let annotations = self . text_annotations ( doc , None ) ;
let mut pos = visual_offset_from_anchor (
let mut pos = visual_offset_from_anchor (
text ,
text ,
self . offset. anchor ,
view_ offset. anchor ,
pos ,
pos ,
& text_fmt ,
& text_fmt ,
& annotations ,
& annotations ,
@ -417,14 +415,14 @@ impl View {
)
)
. ok ( ) ?
. ok ( ) ?
. 0 ;
. 0 ;
if pos . row < self . offset. vertical_offset {
if pos . row < view_ offset. vertical_offset {
return None ;
return None ;
}
}
pos . row - = self . offset. vertical_offset ;
pos . row - = view_ offset. vertical_offset ;
if pos . row > = viewport . height as usize {
if pos . row > = viewport . height as usize {
return None ;
return None ;
}
}
pos . col = pos . col . saturating_sub ( self . offset. horizontal_offset ) ;
pos . col = pos . col . saturating_sub ( view_ offset. horizontal_offset ) ;
Some ( pos )
Some ( pos )
}
}
@ -488,7 +486,7 @@ impl View {
doc ,
doc ,
cursor ,
cursor ,
width ,
width ,
self . offset . horizontal_offset ,
doc . view_offset ( self . id ) . horizontal_offset ,
config ,
config ,
) ) ;
) ) ;
}
}
@ -535,13 +533,14 @@ impl View {
ignore_virtual_text : bool ,
ignore_virtual_text : bool ,
) -> Option < usize > {
) -> Option < usize > {
let text = doc . text ( ) . slice ( .. ) ;
let text = doc . text ( ) . slice ( .. ) ;
let view_offset = doc . view_offset ( self . id ) ;
let text_row = row as usize + self . offset. vertical_offset ;
let text_row = row as usize + view_ offset. vertical_offset ;
let text_col = column as usize + self . offset. horizontal_offset ;
let text_col = column as usize + view_ offset. horizontal_offset ;
let ( char_idx , virt_lines ) = char_idx_at_visual_offset (
let ( char_idx , virt_lines ) = char_idx_at_visual_offset (
text ,
text ,
self . offset. anchor ,
view_ offset. anchor ,
text_row as isize ,
text_row as isize ,
text_col ,
text_col ,
& text_fmt ,
& text_fmt ,
@ -689,11 +688,12 @@ mod tests {
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let doc = Document ::from (
let mut doc = Document ::from (
rope ,
rope ,
None ,
None ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
) ;
) ;
doc . ensure_view_init ( view . id ) ;
assert_eq! (
assert_eq! (
view . text_pos_at_screen_coords (
view . text_pos_at_screen_coords (
@ -863,11 +863,12 @@ mod tests {
) ;
) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let doc = Document ::from (
let mut doc = Document ::from (
rope ,
rope ,
None ,
None ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
) ;
) ;
doc . ensure_view_init ( view . id ) ;
assert_eq! (
assert_eq! (
view . text_pos_at_screen_coords (
view . text_pos_at_screen_coords (
& doc ,
& doc ,
@ -892,11 +893,12 @@ mod tests {
) ;
) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let rope = Rope ::from_str ( "abc\n\tdef" ) ;
let doc = Document ::from (
let mut doc = Document ::from (
rope ,
rope ,
None ,
None ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
) ;
) ;
doc . ensure_view_init ( view . id ) ;
assert_eq! (
assert_eq! (
view . text_pos_at_screen_coords (
view . text_pos_at_screen_coords (
& doc ,
& doc ,
@ -915,11 +917,12 @@ mod tests {
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
let rope = Rope ::from_str ( "Hi! こんにちは皆さん" ) ;
let rope = Rope ::from_str ( "Hi! こんにちは皆さん" ) ;
let doc = Document ::from (
let mut doc = Document ::from (
rope ,
rope ,
None ,
None ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
) ;
) ;
doc . ensure_view_init ( view . id ) ;
assert_eq! (
assert_eq! (
view . text_pos_at_screen_coords (
view . text_pos_at_screen_coords (
@ -998,11 +1001,12 @@ mod tests {
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
let mut view = View ::new ( DocumentId ::default ( ) , GutterConfig ::default ( ) ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
view . area = Rect ::new ( 40 , 40 , 40 , 40 ) ;
let rope = Rope ::from_str ( "Hèl̀l̀ò world!" ) ;
let rope = Rope ::from_str ( "Hèl̀l̀ò world!" ) ;
let doc = Document ::from (
let mut doc = Document ::from (
rope ,
rope ,
None ,
None ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
Arc ::new ( ArcSwap ::new ( Arc ::new ( Config ::default ( ) ) ) ) ,
) ;
) ;
doc . ensure_view_init ( view . id ) ;
assert_eq! (
assert_eq! (
view . text_pos_at_screen_coords (
view . text_pos_at_screen_coords (