address PR review feedbacks

- fix calculation of the new view center

- add default key bindings
This commit is contained in:
Jiangbin Zhao 2022-05-13 11:39:50 -07:00
parent d95114e43f
commit 7f1903249a
2 changed files with 76 additions and 39 deletions

View File

@ -423,6 +423,16 @@ key = "z z"
command = "center_of_window"
mode = "nv"
[[keymaps]]
key = "z t"
command = "top_of_window"
mode = "nv"
[[keymaps]]
key = "z b"
command = "bottom_of_window"
mode = "nv"
[[keymaps]]
key = "d"
command = "delete_forward"

View File

@ -1,4 +1,4 @@
use std::{iter::Iterator, sync::Arc};
use std::{iter::Iterator, sync::Arc, ops::Sub};
use druid::{
piet::PietText, BoxConstraints, Command, Data, Env, Event, EventCtx, LayoutCtx,
@ -11,7 +11,7 @@
CommandKind, EnsureVisiblePosition, LapceCommand, LapceUICommand,
LAPCE_COMMAND, LAPCE_UI_COMMAND,
},
config::LapceTheme,
config::{LapceTheme, EditorConfig},
data::{
EditorTabChild, EditorView, FocusArea, LapceTabData, PanelData, PanelKind,
},
@ -271,6 +271,63 @@ fn ensure_rect_visible(
}
}
// Calculate the new view (as a Rect) for cursor to be at `position`.
// `cursor_center` is where the cursor is currently.
fn view_rect_for_position(
position: &EnsureVisiblePosition,
cursor_center: Point,
editor_size: &Size,
editor_config: &EditorConfig,
) -> Rect {
// TODO: scroll margin (in number of lines) should be configurable.
const MARGIN_LINES: usize = 1;
let line_height = editor_config.line_height;
// The origin of a rect is its top-left corner. Inflating a point
// creates a rect that centers at the point.
let half_width = (editor_size.width / 2.0).ceil();
let half_height = (editor_size.height / 2.0).ceil();
// Find the top edge of the cursor.
let cursor_top = cursor_center.sub(
(0.0, ((line_height as f64) * 0.5).floor())
);
// Find where the center of the rect to show in the editor view.
let view_center = match position {
EnsureVisiblePosition::CenterOfWindow => {
// Cursor line will be at the center of the view.
cursor_top
},
EnsureVisiblePosition::TopOfWindow => {
// Cursor line will be at the top edge of the view, thus the
// view center will be below the current cursor.y by
// `half_height` minus `margin`.
let h = (half_height as usize)
.saturating_sub(MARGIN_LINES * line_height);
Point::new(cursor_top.x, cursor_top.y + (h as f64))
// TODO: When the cursor is near the top of the *buffer*, the
// view will not move for this command. We need an ephemeral
// message, on the status bar for example, to inform the user.
// This is not an error or warning.
},
EnsureVisiblePosition::BottomOfWindow => {
// Cursor line will be shown at the bottom edge of the window,
// thus the view center will be above the current cursor.y by
// `half_height` minus `margin`.
let h = (half_height as usize)
// Plus 1 to compensate for cursor_top.
.saturating_sub((MARGIN_LINES + 1) * line_height);
let y = cursor_top.y as usize;
let y = if y > h { y - h } else { y };
Point::new(cursor_top.x, y as f64)
// TODO: See above for when cursor is near the top of the
// *buffer*.
}
};
Rect::ZERO.with_origin(view_center).inflate(half_width, half_height)
}
pub fn ensure_cursor_position(
&mut self,
ctx: &mut EventCtx,
@ -279,45 +336,15 @@ pub fn ensure_cursor_position(
position: &EnsureVisiblePosition,
env: &Env,
) {
// This is where the cursor currently is.
let cursor = Self::cursor_region(data, ctx.text()).center();
// FIXME: need to see how LapceEditorBufferData::scroll() handles the
// margin
//
// TODO: scroll margin (in number of lines) should be configurable
let margin = data.config.editor.line_height * 2;
// The origin of a rect is its top-left corner. Inflating a point
// creates a rect that centers at the point.
let width = (data.editor.size.borrow().width / 2.0).ceil();
let height = (data.editor.size.borrow().height / 2.0).ceil();
// Find where the center will be.
let center = match position {
EnsureVisiblePosition::CenterOfWindow => {
// Cursor line will be at the center of the view.
cursor
},
EnsureVisiblePosition::TopOfWindow => {
// Cursor line will be at the top edge, thus center of the view
// is half height down.
let h = height as usize;
let h = if h > margin { h - margin } else { margin };
Point::new(cursor.x, cursor.y + h as f64)
},
EnsureVisiblePosition::BottomOfWindow => {
// Cursor line will be at the bottom edge, thus center of the
// view is half height up.
let h = height as usize;
let h = if h > margin { h - margin } else { margin };
let y = cursor.y as usize;
let y = if h > y { y } else { y - h };
Point::new(cursor.x, y as f64)
}
};
let rect = Rect::ZERO.with_origin(center).inflate(width, height);
// This is where the cursor currently is, relative to the buffer's
// origin.
let cursor_center = Self::cursor_region(data, ctx.text()).center();
let editor_size = *data.editor.size.borrow();
let rect = Self::view_rect_for_position(
position, cursor_center, &editor_size, &data.config.editor
);
let size = LapceEditor::get_size(data, ctx.text(), editor_size, panels, env);
let scroll = self.editor.widget_mut().editor.widget_mut().inner_mut();
scroll.set_child_size(size);