Implement scrolling for editor2 (#3251)

Release Notes:

- N/A
This commit is contained in:
Antonio Scandurra 2023-11-07 17:53:57 +01:00 committed by GitHub
commit 64b899c68c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 402 additions and 377 deletions

View File

@ -36,9 +36,9 @@ pub use element::{
use futures::FutureExt; use futures::FutureExt;
use fuzzy::{StringMatch, StringMatchCandidate}; use fuzzy::{StringMatch, StringMatchCandidate};
use gpui::{ use gpui::{
div, px, AnyElement, AppContext, BackgroundExecutor, Context, Div, Element, EventEmitter, div, px, AnyElement, AppContext, BackgroundExecutor, Context, Div, Element, Entity,
FocusHandle, FontStyle, FontWeight, Hsla, Model, Pixels, Render, Styled, Subscription, Task, EventEmitter, FocusHandle, FontStyle, FontWeight, Hsla, Model, Pixels, Render, Styled,
TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext, Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext,
}; };
use highlight_matching_bracket::refresh_matching_bracket_highlights; use highlight_matching_bracket::refresh_matching_bracket_highlights;
use hover_popover::{hide_hover, HoverState}; use hover_popover::{hide_hover, HoverState};

View File

@ -9,8 +9,9 @@ use anyhow::Result;
use collections::{BTreeMap, HashMap}; use collections::{BTreeMap, HashMap};
use gpui::{ use gpui::{
black, hsla, point, px, relative, size, transparent_black, AnyElement, BorrowWindow, Bounds, black, hsla, point, px, relative, size, transparent_black, AnyElement, BorrowWindow, Bounds,
ContentMask, Corners, Edges, Element, Hsla, Line, Pixels, ShapedGlyph, Size, Style, TextRun, ContentMask, Corners, DispatchPhase, Edges, Element, ElementId, Hsla, Line, Pixels,
TextStyle, TextSystem, ViewContext, WindowContext, ScrollWheelEvent, ShapedGlyph, Size, StatefulInteraction, Style, TextRun, TextStyle,
TextSystem, ViewContext, WindowContext,
}; };
use itertools::Itertools; use itertools::Itertools;
use language::language_settings::ShowWhitespaceSetting; use language::language_settings::ShowWhitespaceSetting;
@ -464,39 +465,41 @@ impl EditorElement {
// true // true
// } // }
// fn scroll( fn scroll(
// editor: &mut Editor, editor: &mut Editor,
// position: gpui::Point<Pixels>, event: &ScrollWheelEvent,
// mut delta: gpui::Point<Pixels>, position_map: &PositionMap,
// precise: bool, bounds: Bounds<Pixels>,
// position_map: &PositionMap, cx: &mut ViewContext<Editor>,
// bounds: Bounds<Pixels>, ) -> bool {
// cx: &mut ViewContext<Editor>, if !bounds.contains_point(&event.position) {
// ) -> bool { return false;
// if !bounds.contains_point(position) { }
// return false;
// }
// let line_height = position_map.line_height; let line_height = position_map.line_height;
// let max_glyph_width = position_map.em_width; let max_glyph_width = position_map.em_width;
let (delta, axis) = match event.delta {
gpui::ScrollDelta::Pixels(mut pixels) => {
//Trackpad
let axis = position_map.snapshot.ongoing_scroll.filter(&mut pixels);
(pixels, axis)
}
// let axis = if precise { gpui::ScrollDelta::Lines(lines) => {
// //Trackpad //Not trackpad
// position_map.snapshot.ongoing_scroll.filter(&mut delta) let pixels = point(lines.x * max_glyph_width, lines.y * line_height);
// } else { (pixels, None)
// //Not trackpad }
// delta *= point(max_glyph_width, line_height); };
// None //Resets ongoing scroll
// };
// let scroll_position = position_map.snapshot.scroll_position(); let scroll_position = position_map.snapshot.scroll_position();
// let x = (scroll_position.x * max_glyph_width - delta.x) / max_glyph_width; let x = f32::from((scroll_position.x * max_glyph_width - delta.x) / max_glyph_width);
// let y = (scroll_position.y * line_height - delta.y) / line_height; let y = f32::from((scroll_position.y * line_height - delta.y) / line_height);
// let scroll_position = point(x, y).clamp(gpui::Point::<Pixels>::zero(), position_map.scroll_max); let scroll_position = point(x, y).clamp(&point(0., 0.), &position_map.scroll_max);
// editor.scroll(scroll_position, axis, cx); editor.scroll(scroll_position, axis, cx);
// true true
// } }
fn paint_background( fn paint_background(
&self, &self,
@ -774,91 +777,72 @@ impl EditorElement {
let line_end_overshoot = 0.15 * layout.position_map.line_height; let line_end_overshoot = 0.15 * layout.position_map.line_height;
let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces; let whitespace_setting = editor.buffer.read(cx).settings_at(0, cx).show_whitespaces;
// todo!("cursor region") cx.with_content_mask(ContentMask { bounds }, |cx| {
// cx.scene().push_cursor_region(CursorRegion { // todo!("cursor region")
// bounds, // cx.scene().push_cursor_region(CursorRegion {
// style: if !editor.link_go_to_definition_state.definitions.is_empty { // bounds,
// CursorStyle::PointingHand // style: if !editor.link_go_to_definition_state.definitions.is_empty {
// } else { // CursorStyle::PointingHand
// CursorStyle::IBeam // } else {
// }, // CursorStyle::IBeam
// }); // },
// });
// todo!("fold ranges") // todo!("fold ranges")
// let fold_corner_radius = // let fold_corner_radius =
// self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height; // self.style.folds.ellipses.corner_radius_factor * layout.position_map.line_height;
// for (id, range, color) in layout.fold_ranges.iter() { // for (id, range, color) in layout.fold_ranges.iter() {
// self.paint_highlighted_range( // self.paint_highlighted_range(
// range.clone(), // range.clone(),
// *color, // *color,
// fold_corner_radius, // fold_corner_radius,
// fold_corner_radius * 2., // fold_corner_radius * 2.,
// layout, // layout,
// content_origin, // content_origin,
// scroll_top, // scroll_top,
// scroll_left, // scroll_left,
// bounds, // bounds,
// cx, // cx,
// ); // );
// for bound in range_to_bounds( // for bound in range_to_bounds(
// &range, // &range,
// content_origin, // content_origin,
// scroll_left, // scroll_left,
// scroll_top, // scroll_top,
// &layout.visible_display_row_range, // &layout.visible_display_row_range,
// line_end_overshoot, // line_end_overshoot,
// &layout.position_map, // &layout.position_map,
// ) { // ) {
// cx.scene().push_cursor_region(CursorRegion { // cx.scene().push_cursor_region(CursorRegion {
// bounds: bound, // bounds: bound,
// style: CursorStyle::PointingHand, // style: CursorStyle::PointingHand,
// }); // });
// let display_row = range.start.row(); // let display_row = range.start.row();
// let buffer_row = DisplayPoint::new(display_row, 0) // let buffer_row = DisplayPoint::new(display_row, 0)
// .to_point(&layout.position_map.snapshot.display_snapshot) // .to_point(&layout.position_map.snapshot.display_snapshot)
// .row; // .row;
// let view_id = cx.view_id(); // let view_id = cx.view_id();
// cx.scene().push_mouse_region( // cx.scene().push_mouse_region(
// MouseRegion::new::<FoldMarkers>(view_id, *id as usize, bound) // MouseRegion::new::<FoldMarkers>(view_id, *id as usize, bound)
// .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| { // .on_click(MouseButton::Left, move |_, editor: &mut Editor, cx| {
// editor.unfold_at(&UnfoldAt { buffer_row }, cx) // editor.unfold_at(&UnfoldAt { buffer_row }, cx)
// }) // })
// .with_notify_on_hover(true) // .with_notify_on_hover(true)
// .with_notify_on_click(true), // .with_notify_on_click(true),
// ) // )
// } // }
// } // }
for (range, color) in &layout.highlighted_ranges { for (range, color) in &layout.highlighted_ranges {
self.paint_highlighted_range(
range.clone(),
*color,
Pixels::ZERO,
line_end_overshoot,
layout,
content_origin,
scroll_top,
scroll_left,
bounds,
cx,
);
}
let mut cursors = SmallVec::<[Cursor; 32]>::new();
let corner_radius = 0.15 * layout.position_map.line_height;
let mut invisible_display_ranges = SmallVec::<[Range<DisplayPoint>; 32]>::new();
for (selection_style, selections) in &layout.selections {
for selection in selections {
self.paint_highlighted_range( self.paint_highlighted_range(
selection.range.clone(), range.clone(),
selection_style.selection, *color,
corner_radius, Pixels::ZERO,
corner_radius * 2., line_end_overshoot,
layout, layout,
content_origin, content_origin,
scroll_top, scroll_top,
@ -866,205 +850,226 @@ impl EditorElement {
bounds, bounds,
cx, cx,
); );
}
if selection.is_local && !selection.range.is_empty() { let mut cursors = SmallVec::<[Cursor; 32]>::new();
invisible_display_ranges.push(selection.range.clone()); let corner_radius = 0.15 * layout.position_map.line_height;
} let mut invisible_display_ranges = SmallVec::<[Range<DisplayPoint>; 32]>::new();
if !selection.is_local || editor.show_local_cursors(cx) { for (selection_style, selections) in &layout.selections {
let cursor_position = selection.head; for selection in selections {
if layout self.paint_highlighted_range(
.visible_display_row_range selection.range.clone(),
.contains(&cursor_position.row()) selection_style.selection,
{ corner_radius,
let cursor_row_layout = &layout.position_map.line_layouts corner_radius * 2.,
[(cursor_position.row() - start_row) as usize] layout,
.line; content_origin,
let cursor_column = cursor_position.column() as usize; scroll_top,
scroll_left,
bounds,
cx,
);
let cursor_character_x = cursor_row_layout.x_for_index(cursor_column); if selection.is_local && !selection.range.is_empty() {
let mut block_width = invisible_display_ranges.push(selection.range.clone());
cursor_row_layout.x_for_index(cursor_column + 1) - cursor_character_x; }
if block_width == Pixels::ZERO {
block_width = layout.position_map.em_width; if !selection.is_local || editor.show_local_cursors(cx) {
let cursor_position = selection.head;
if layout
.visible_display_row_range
.contains(&cursor_position.row())
{
let cursor_row_layout = &layout.position_map.line_layouts
[(cursor_position.row() - start_row) as usize]
.line;
let cursor_column = cursor_position.column() as usize;
let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
let mut block_width = cursor_row_layout.x_for_index(cursor_column + 1)
- cursor_character_x;
if block_width == Pixels::ZERO {
block_width = layout.position_map.em_width;
}
let block_text = if let CursorShape::Block = selection.cursor_shape {
layout
.position_map
.snapshot
.chars_at(cursor_position)
.next()
.and_then(|(character, _)| {
let text = character.to_string();
cx.text_system()
.layout_text(
&text,
cursor_row_layout.font_size,
&[TextRun {
len: text.len(),
font: self.style.text.font(),
color: self.style.background,
underline: None,
}],
None,
)
.unwrap()
.pop()
})
} else {
None
};
let x = cursor_character_x - scroll_left;
let y = cursor_position.row() as f32 * layout.position_map.line_height
- scroll_top;
if selection.is_newest {
editor.pixel_position_of_newest_cursor = Some(point(
bounds.origin.x + x + block_width / 2.,
bounds.origin.y + y + layout.position_map.line_height / 2.,
));
}
cursors.push(Cursor {
color: selection_style.cursor,
block_width,
origin: point(x, y),
line_height: layout.position_map.line_height,
shape: selection.cursor_shape,
block_text,
});
} }
let block_text = if let CursorShape::Block = selection.cursor_shape {
layout
.position_map
.snapshot
.chars_at(cursor_position)
.next()
.and_then(|(character, _)| {
let text = character.to_string();
cx.text_system()
.layout_text(
&text,
cursor_row_layout.font_size,
&[TextRun {
len: text.len(),
font: self.style.text.font(),
color: self.style.background,
underline: None,
}],
None,
)
.unwrap()
.pop()
})
} else {
None
};
let x = cursor_character_x - scroll_left;
let y = cursor_position.row() as f32 * layout.position_map.line_height
- scroll_top;
if selection.is_newest {
editor.pixel_position_of_newest_cursor = Some(point(
bounds.origin.x + x + block_width / 2.,
bounds.origin.y + y + layout.position_map.line_height / 2.,
));
}
cursors.push(Cursor {
color: selection_style.cursor,
block_width,
origin: point(x, y),
line_height: layout.position_map.line_height,
shape: selection.cursor_shape,
block_text,
});
} }
} }
} }
}
for (ix, line_with_invisibles) in layout.position_map.line_layouts.iter().enumerate() { for (ix, line_with_invisibles) in layout.position_map.line_layouts.iter().enumerate() {
let row = start_row + ix as u32; let row = start_row + ix as u32;
line_with_invisibles.draw( line_with_invisibles.draw(
layout, layout,
row, row,
scroll_top, scroll_top,
content_origin, content_origin,
scroll_left, scroll_left,
whitespace_setting, whitespace_setting,
&invisible_display_ranges, &invisible_display_ranges,
cx, cx,
) )
}
cx.stack(9999, |cx| {
for cursor in cursors {
cursor.paint(content_origin, cx);
} }
});
// cx.scene().push_layer(Some(bounds));
// cx.scene().pop_layer(); cx.stack(0, |cx| {
for cursor in cursors {
cursor.paint(content_origin, cx);
}
});
// cx.scene().push_layer(Some(bounds));
// if let Some((position, context_menu)) = layout.context_menu.as_mut() { // cx.scene().pop_layer();
// cx.scene().push_stacking_context(None, None);
// let cursor_row_layout =
// &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
// let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left;
// let y = (position.row() + 1) as f32 * layout.position_map.line_height - scroll_top;
// let mut list_origin = content_origin + point(x, y);
// let list_width = context_menu.size().x;
// let list_height = context_menu.size().y;
// // Snap the right edge of the list to the right edge of the window if // if let Some((position, context_menu)) = layout.context_menu.as_mut() {
// // its horizontal bounds overflow. // cx.scene().push_stacking_context(None, None);
// if list_origin.x + list_width > cx.window_size().x { // let cursor_row_layout =
// list_origin.set_x((cx.window_size().x - list_width).max(0.)); // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
// } // let x = cursor_row_layout.x_for_index(position.column() as usize) - scroll_left;
// let y = (position.row() + 1) as f32 * layout.position_map.line_height - scroll_top;
// let mut list_origin = content_origin + point(x, y);
// let list_width = context_menu.size().x;
// let list_height = context_menu.size().y;
// if list_origin.y + list_height > bounds.max_y { // // Snap the right edge of the list to the right edge of the window if
// list_origin // // its horizontal bounds overflow.
// .set_y(list_origin.y - layout.position_map.line_height - list_height); // if list_origin.x + list_width > cx.window_size().x {
// } // list_origin.set_x((cx.window_size().x - list_width).max(0.));
// }
// context_menu.paint( // if list_origin.y + list_height > bounds.max_y {
// list_origin, // list_origin
// Bounds::<Pixels>::from_points( // .set_y(list_origin.y - layout.position_map.line_height - list_height);
// gpui::Point::<Pixels>::zero(), // }
// point(f32::MAX, f32::MAX),
// ), // Let content bleed outside of editor
// editor,
// cx,
// );
// cx.scene().pop_stacking_context(); // context_menu.paint(
// } // list_origin,
// Bounds::<Pixels>::from_points(
// gpui::Point::<Pixels>::zero(),
// point(f32::MAX, f32::MAX),
// ), // Let content bleed outside of editor
// editor,
// cx,
// );
// if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() { // cx.scene().pop_stacking_context();
// cx.scene().push_stacking_context(None, None); // }
// // This is safe because we check on layout whether the required row is available // if let Some((position, hover_popovers)) = layout.hover_popovers.as_mut() {
// let hovered_row_layout = // cx.scene().push_stacking_context(None, None);
// &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
// // Minimum required size: Take the first popover, and add 1.5 times the minimum popover // // This is safe because we check on layout whether the required row is available
// // height. This is the size we will use to decide whether to render popovers above or below // let hovered_row_layout =
// // the hovered line. // &layout.position_map.line_layouts[(position.row() - start_row) as usize].line;
// let first_size = hover_popovers[0].size();
// let height_to_reserve = first_size.y
// + 1.5 * MIN_POPOVER_LINE_HEIGHT as f32 * layout.position_map.line_height;
// // Compute Hovered Point // // Minimum required size: Take the first popover, and add 1.5 times the minimum popover
// let x = hovered_row_layout.x_for_index(position.column() as usize) - scroll_left; // // height. This is the size we will use to decide whether to render popovers above or below
// let y = position.row() as f32 * layout.position_map.line_height - scroll_top; // // the hovered line.
// let hovered_point = content_origin + point(x, y); // let first_size = hover_popovers[0].size();
// let height_to_reserve = first_size.y
// + 1.5 * MIN_POPOVER_LINE_HEIGHT as f32 * layout.position_map.line_height;
// if hovered_point.y - height_to_reserve > 0.0 { // // Compute Hovered Point
// // There is enough space above. Render popovers above the hovered point // let x = hovered_row_layout.x_for_index(position.column() as usize) - scroll_left;
// let mut current_y = hovered_point.y; // let y = position.row() as f32 * layout.position_map.line_height - scroll_top;
// for hover_popover in hover_popovers { // let hovered_point = content_origin + point(x, y);
// let size = hover_popover.size();
// let mut popover_origin = point(hovered_point.x, current_y - size.y);
// let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); // if hovered_point.y - height_to_reserve > 0.0 {
// if x_out_of_bounds < 0.0 { // // There is enough space above. Render popovers above the hovered point
// popover_origin.set_x(popover_origin.x + x_out_of_bounds); // let mut current_y = hovered_point.y;
// } // for hover_popover in hover_popovers {
// let size = hover_popover.size();
// let mut popover_origin = point(hovered_point.x, current_y - size.y);
// hover_popover.paint( // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x);
// popover_origin, // if x_out_of_bounds < 0.0 {
// Bounds::<Pixels>::from_points( // popover_origin.set_x(popover_origin.x + x_out_of_bounds);
// gpui::Point::<Pixels>::zero(), // }
// point(f32::MAX, f32::MAX),
// ), // Let content bleed outside of editor
// editor,
// cx,
// );
// current_y = popover_origin.y - HOVER_POPOVER_GAP; // hover_popover.paint(
// } // popover_origin,
// } else { // Bounds::<Pixels>::from_points(
// // There is not enough space above. Render popovers below the hovered point // gpui::Point::<Pixels>::zero(),
// let mut current_y = hovered_point.y + layout.position_map.line_height; // point(f32::MAX, f32::MAX),
// for hover_popover in hover_popovers { // ), // Let content bleed outside of editor
// let size = hover_popover.size(); // editor,
// let mut popover_origin = point(hovered_point.x, current_y); // cx,
// );
// let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x); // current_y = popover_origin.y - HOVER_POPOVER_GAP;
// if x_out_of_bounds < 0.0 { // }
// popover_origin.set_x(popover_origin.x + x_out_of_bounds); // } else {
// } // // There is not enough space above. Render popovers below the hovered point
// let mut current_y = hovered_point.y + layout.position_map.line_height;
// for hover_popover in hover_popovers {
// let size = hover_popover.size();
// let mut popover_origin = point(hovered_point.x, current_y);
// hover_popover.paint( // let x_out_of_bounds = bounds.max_x - (popover_origin.x + size.x);
// popover_origin, // if x_out_of_bounds < 0.0 {
// Bounds::<Pixels>::from_points( // popover_origin.set_x(popover_origin.x + x_out_of_bounds);
// gpui::Point::<Pixels>::zero(), // }
// point(f32::MAX, f32::MAX),
// ), // Let content bleed outside of editor
// editor,
// cx,
// );
// current_y = popover_origin.y + size.y + HOVER_POPOVER_GAP; // hover_popover.paint(
// } // popover_origin,
// } // Bounds::<Pixels>::from_points(
// gpui::Point::<Pixels>::zero(),
// point(f32::MAX, f32::MAX),
// ), // Let content bleed outside of editor
// editor,
// cx,
// );
// cx.scene().pop_stacking_context(); // current_y = popover_origin.y + size.y + HOVER_POPOVER_GAP;
// } // }
// }
// cx.scene().pop_stacking_context();
// }
})
} }
fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels { fn scrollbar_left(&self, bounds: &Bounds<Pixels>) -> Pixels {
@ -2573,6 +2578,20 @@ impl Element<Editor> for EditorElement {
cx: &mut gpui::ViewContext<Editor>, cx: &mut gpui::ViewContext<Editor>,
) { ) {
let layout = self.compute_layout(editor, cx, bounds); let layout = self.compute_layout(editor, cx, bounds);
cx.on_mouse_event({
let position_map = layout.position_map.clone();
move |editor, event: &ScrollWheelEvent, phase, cx| {
if phase != DispatchPhase::Bubble {
return;
}
if Self::scroll(editor, event, &position_map, bounds, cx) {
cx.stop_propagation();
}
}
});
cx.with_content_mask(ContentMask { bounds }, |cx| { cx.with_content_mask(ContentMask { bounds }, |cx| {
let gutter_bounds = Bounds { let gutter_bounds = Bounds {
origin: bounds.origin, origin: bounds.origin,

View File

@ -1,4 +1,6 @@
use gpui::AppContext; use super::Axis;
use crate::Editor;
use gpui::{AppContext, Point, ViewContext};
// actions!( // actions!(
// editor, // editor,
@ -42,107 +44,107 @@ pub fn init(cx: &mut AppContext) {
// }); // });
} }
// impl Editor { impl Editor {
// pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) -> Option<()> { // pub fn next_screen(&mut self, _: &NextScreen, cx: &mut ViewContext<Editor>) -> Option<()> {
// if self.take_rename(true, cx).is_some() { // if self.take_rename(true, cx).is_some() {
// return None; // return None;
// } // }
// if self.mouse_context_menu.read(cx).visible() { // if self.mouse_context_menu.read(cx).visible() {
// return None; // return None;
// } // }
// if matches!(self.mode, EditorMode::SingleLine) { // if matches!(self.mode, EditorMode::SingleLine) {
// cx.propagate_action(); // cx.propagate_action();
// return None; // return None;
// } // }
// self.request_autoscroll(Autoscroll::Next, cx); // self.request_autoscroll(Autoscroll::Next, cx);
// Some(()) // Some(())
// } // }
// pub fn scroll( pub fn scroll(
// &mut self, &mut self,
// scroll_position: Vector2F, scroll_position: Point<f32>,
// axis: Option<Axis>, axis: Option<Axis>,
// cx: &mut ViewContext<Self>, cx: &mut ViewContext<Self>,
// ) { ) {
// self.scroll_manager.update_ongoing_scroll(axis); self.scroll_manager.update_ongoing_scroll(axis);
// self.set_scroll_position(scroll_position, cx); self.set_scroll_position(scroll_position, cx);
// } }
// fn scroll_cursor_top(editor: &mut Editor, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) { // fn scroll_cursor_top(editor: &mut Editor, _: &ScrollCursorTop, cx: &mut ViewContext<Editor>) {
// let snapshot = editor.snapshot(cx).display_snapshot; // let snapshot = editor.snapshot(cx).display_snapshot;
// let scroll_margin_rows = editor.vertical_scroll_margin() as u32; // let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
// let mut new_screen_top = editor.selections.newest_display(cx).head(); // let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(scroll_margin_rows); // *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(scroll_margin_rows);
// *new_screen_top.column_mut() = 0; // *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left); // let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top); // let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// editor.set_scroll_anchor( // editor.set_scroll_anchor(
// ScrollAnchor { // ScrollAnchor {
// anchor: new_anchor, // anchor: new_anchor,
// offset: Default::default(), // offset: Default::default(),
// }, // },
// cx, // cx,
// ) // )
// } // }
// fn scroll_cursor_center( // fn scroll_cursor_center(
// editor: &mut Editor, // editor: &mut Editor,
// _: &ScrollCursorCenter, // _: &ScrollCursorCenter,
// cx: &mut ViewContext<Editor>, // cx: &mut ViewContext<Editor>,
// ) { // ) {
// let snapshot = editor.snapshot(cx).display_snapshot; // let snapshot = editor.snapshot(cx).display_snapshot;
// let visible_rows = if let Some(visible_rows) = editor.visible_line_count() { // let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
// visible_rows as u32 // visible_rows as u32
// } else { // } else {
// return; // return;
// }; // };
// let mut new_screen_top = editor.selections.newest_display(cx).head(); // let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(visible_rows / 2); // *new_screen_top.row_mut() = new_screen_top.row().saturating_sub(visible_rows / 2);
// *new_screen_top.column_mut() = 0; // *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left); // let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top); // let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// editor.set_scroll_anchor( // editor.set_scroll_anchor(
// ScrollAnchor { // ScrollAnchor {
// anchor: new_anchor, // anchor: new_anchor,
// offset: Default::default(), // offset: Default::default(),
// }, // },
// cx, // cx,
// ) // )
// } // }
// fn scroll_cursor_bottom( // fn scroll_cursor_bottom(
// editor: &mut Editor, // editor: &mut Editor,
// _: &ScrollCursorBottom, // _: &ScrollCursorBottom,
// cx: &mut ViewContext<Editor>, // cx: &mut ViewContext<Editor>,
// ) { // ) {
// let snapshot = editor.snapshot(cx).display_snapshot; // let snapshot = editor.snapshot(cx).display_snapshot;
// let scroll_margin_rows = editor.vertical_scroll_margin() as u32; // let scroll_margin_rows = editor.vertical_scroll_margin() as u32;
// let visible_rows = if let Some(visible_rows) = editor.visible_line_count() { // let visible_rows = if let Some(visible_rows) = editor.visible_line_count() {
// visible_rows as u32 // visible_rows as u32
// } else { // } else {
// return; // return;
// }; // };
// let mut new_screen_top = editor.selections.newest_display(cx).head(); // let mut new_screen_top = editor.selections.newest_display(cx).head();
// *new_screen_top.row_mut() = new_screen_top // *new_screen_top.row_mut() = new_screen_top
// .row() // .row()
// .saturating_sub(visible_rows.saturating_sub(scroll_margin_rows)); // .saturating_sub(visible_rows.saturating_sub(scroll_margin_rows));
// *new_screen_top.column_mut() = 0; // *new_screen_top.column_mut() = 0;
// let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left); // let new_screen_top = new_screen_top.to_offset(&snapshot, Bias::Left);
// let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top); // let new_anchor = snapshot.buffer_snapshot.anchor_before(new_screen_top);
// editor.set_scroll_anchor( // editor.set_scroll_anchor(
// ScrollAnchor { // ScrollAnchor {
// anchor: new_anchor, // anchor: new_anchor,
// offset: Default::default(), // offset: Default::default(),
// }, // },
// cx, // cx,
// ) // )
// } // }
// } }

View File

@ -124,6 +124,10 @@ where
}, },
} }
} }
pub fn clamp(&self, min: &Self, max: &Self) -> Self {
self.max(min).min(max)
}
} }
impl<T: Clone + Default + Debug> Clone for Point<T> { impl<T: Clone + Default + Debug> Clone for Point<T> {