mirror of
https://github.com/zed-industries/zed.git
synced 2024-09-20 02:47:34 +03:00
Autoscroll when leader moves cursors
instead of copying their scroll top. Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
fad299eb3f
commit
fa62fd968f
@ -439,7 +439,7 @@ pub struct Editor {
|
|||||||
active_diagnostics: Option<ActiveDiagnosticGroup>,
|
active_diagnostics: Option<ActiveDiagnosticGroup>,
|
||||||
scroll_position: Vector2F,
|
scroll_position: Vector2F,
|
||||||
scroll_top_anchor: Anchor,
|
scroll_top_anchor: Anchor,
|
||||||
autoscroll_request: Option<Autoscroll>,
|
autoscroll_request: Option<(Autoscroll, bool)>,
|
||||||
soft_wrap_mode_override: Option<settings::SoftWrap>,
|
soft_wrap_mode_override: Option<settings::SoftWrap>,
|
||||||
get_field_editor_theme: Option<GetFieldEditorTheme>,
|
get_field_editor_theme: Option<GetFieldEditorTheme>,
|
||||||
override_text_style: Option<Box<OverrideTextStyle>>,
|
override_text_style: Option<Box<OverrideTextStyle>>,
|
||||||
@ -1017,6 +1017,15 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
|
pub fn set_scroll_position(&mut self, scroll_position: Vector2F, cx: &mut ViewContext<Self>) {
|
||||||
|
self.set_scroll_position_internal(scroll_position, true, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_scroll_position_internal(
|
||||||
|
&mut self,
|
||||||
|
scroll_position: Vector2F,
|
||||||
|
local: bool,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
|
|
||||||
if scroll_position.y() == 0. {
|
if scroll_position.y() == 0. {
|
||||||
@ -1035,7 +1044,7 @@ impl Editor {
|
|||||||
self.scroll_top_anchor = anchor;
|
self.scroll_top_anchor = anchor;
|
||||||
}
|
}
|
||||||
|
|
||||||
cx.emit(Event::ScrollPositionChanged { local: true });
|
cx.emit(Event::ScrollPositionChanged { local });
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1090,7 +1099,7 @@ impl Editor {
|
|||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position(scroll_position, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let autoscroll = if let Some(autoscroll) = self.autoscroll_request.take() {
|
let (autoscroll, local) = if let Some(autoscroll) = self.autoscroll_request.take() {
|
||||||
autoscroll
|
autoscroll
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -1142,15 +1151,15 @@ impl Editor {
|
|||||||
|
|
||||||
if target_top < start_row {
|
if target_top < start_row {
|
||||||
scroll_position.set_y(target_top);
|
scroll_position.set_y(target_top);
|
||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position_internal(scroll_position, local, cx);
|
||||||
} else if target_bottom >= end_row {
|
} else if target_bottom >= end_row {
|
||||||
scroll_position.set_y(target_bottom - visible_lines);
|
scroll_position.set_y(target_bottom - visible_lines);
|
||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position_internal(scroll_position, local, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Autoscroll::Center => {
|
Autoscroll::Center => {
|
||||||
scroll_position.set_y((first_cursor_top - margin).max(0.0));
|
scroll_position.set_y((first_cursor_top - margin).max(0.0));
|
||||||
self.set_scroll_position(scroll_position, cx);
|
self.set_scroll_position_internal(scroll_position, local, cx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5111,7 +5120,12 @@ impl Editor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
|
pub fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
|
||||||
self.autoscroll_request = Some(autoscroll);
|
self.autoscroll_request = Some((autoscroll, true));
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn request_autoscroll_remotely(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
|
||||||
|
self.autoscroll_request = Some((autoscroll, false));
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -9054,31 +9068,59 @@ mod tests {
|
|||||||
|cx| build_editor(buffer.clone(), cx),
|
|cx| build_editor(buffer.clone(), cx),
|
||||||
);
|
);
|
||||||
|
|
||||||
follower.update(cx, |_, cx| {
|
let pending_update = Rc::new(RefCell::new(None));
|
||||||
cx.subscribe(&leader, |follower, leader, event, cx| {
|
follower.update(cx, {
|
||||||
let mut update = None;
|
let update = pending_update.clone();
|
||||||
leader
|
|_, cx| {
|
||||||
.read(cx)
|
cx.subscribe(&leader, move |_, leader, event, cx| {
|
||||||
.add_event_to_update_proto(event, &mut update, cx);
|
leader
|
||||||
if let Some(update) = update {
|
.read(cx)
|
||||||
follower.apply_update_proto(update, cx).unwrap();
|
.add_event_to_update_proto(event, &mut *update.borrow_mut(), cx);
|
||||||
}
|
})
|
||||||
})
|
.detach();
|
||||||
.detach();
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update the selections only
|
||||||
leader.update(cx, |leader, cx| {
|
leader.update(cx, |leader, cx| {
|
||||||
leader.select_ranges([1..1], None, cx);
|
leader.select_ranges([1..1], None, cx);
|
||||||
});
|
});
|
||||||
|
follower.update(cx, |follower, cx| {
|
||||||
|
follower
|
||||||
|
.apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
|
assert_eq!(follower.read(cx).selected_ranges(cx), vec![1..1]);
|
||||||
|
|
||||||
|
// Update the scroll position only
|
||||||
leader.update(cx, |leader, cx| {
|
leader.update(cx, |leader, cx| {
|
||||||
leader.set_scroll_position(vec2f(1.5, 3.5), cx);
|
leader.set_scroll_position(vec2f(1.5, 3.5), cx);
|
||||||
});
|
});
|
||||||
|
follower.update(cx, |follower, cx| {
|
||||||
|
follower
|
||||||
|
.apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
follower.update(cx, |follower, cx| follower.scroll_position(cx)),
|
follower.update(cx, |follower, cx| follower.scroll_position(cx)),
|
||||||
vec2f(1.5, 3.5)
|
vec2f(1.5, 3.5)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Update the selections and scroll position
|
||||||
|
leader.update(cx, |leader, cx| {
|
||||||
|
leader.select_ranges([0..0], None, cx);
|
||||||
|
leader.request_autoscroll(Autoscroll::Newest, cx);
|
||||||
|
leader.set_scroll_position(vec2f(1.5, 3.5), cx);
|
||||||
|
});
|
||||||
|
follower.update(cx, |follower, cx| {
|
||||||
|
let initial_scroll_position = follower.scroll_position(cx);
|
||||||
|
follower
|
||||||
|
.apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(follower.scroll_position(cx), initial_scroll_position);
|
||||||
|
assert!(follower.autoscroll_request.is_some());
|
||||||
|
});
|
||||||
|
assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -166,19 +166,6 @@ impl FollowableItem for Editor {
|
|||||||
let excerpt_id = excerpt_id.clone();
|
let excerpt_id = excerpt_id.clone();
|
||||||
drop(buffer);
|
drop(buffer);
|
||||||
|
|
||||||
if let Some(anchor) = message.scroll_top_anchor {
|
|
||||||
self.set_scroll_top_anchor(
|
|
||||||
Anchor {
|
|
||||||
buffer_id: Some(buffer_id),
|
|
||||||
excerpt_id: excerpt_id.clone(),
|
|
||||||
text_anchor: language::proto::deserialize_anchor(anchor)
|
|
||||||
.ok_or_else(|| anyhow!("invalid scroll top"))?,
|
|
||||||
},
|
|
||||||
vec2f(message.scroll_x, message.scroll_y),
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let selections = message
|
let selections = message
|
||||||
.selections
|
.selections
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -188,6 +175,20 @@ impl FollowableItem for Editor {
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
if !selections.is_empty() {
|
if !selections.is_empty() {
|
||||||
self.set_selections(selections.into(), None, false, cx);
|
self.set_selections(selections.into(), None, false, cx);
|
||||||
|
self.request_autoscroll_remotely(Autoscroll::Newest, cx);
|
||||||
|
} else {
|
||||||
|
if let Some(anchor) = message.scroll_top_anchor {
|
||||||
|
self.set_scroll_top_anchor(
|
||||||
|
Anchor {
|
||||||
|
buffer_id: Some(buffer_id),
|
||||||
|
excerpt_id: excerpt_id.clone(),
|
||||||
|
text_anchor: language::proto::deserialize_anchor(anchor)
|
||||||
|
.ok_or_else(|| anyhow!("invalid scroll top"))?,
|
||||||
|
},
|
||||||
|
vec2f(message.scroll_x, message.scroll_y),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user