Position prediction popover adjacent to edit if possible (#24750)
Also, place accept key binding indicator on right edge of popover to avoid obscuring content above. Release Notes: - N/A Co-authored-by: Danilo Leal <daniloleal09@gmail.com> Co-authored-by: rtfeldman <oss@rtfeldman.com> Co-authored-by: Agus Zubiaga <hi@aguz.me>
This commit is contained in:
co-authored by
Danilo Leal
rtfeldman
Agus Zubiaga
parent
eea6b526dc
commit
316b97d6e3
@@ -3808,39 +3808,38 @@ impl EditorElement {
|
||||
);
|
||||
|
||||
let styled_text = highlighted_edits.to_styled_text(&style.text);
|
||||
let line_count = highlighted_edits.text.lines().count();
|
||||
|
||||
const ACCEPT_INDICATOR_HEIGHT: Pixels = px(24.);
|
||||
const BORDER_WIDTH: Pixels = px(1.);
|
||||
|
||||
let mut element = v_flex()
|
||||
.items_end()
|
||||
let mut element = h_flex()
|
||||
.items_start()
|
||||
.child(
|
||||
div()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.border(BORDER_WIDTH)
|
||||
.shadow_sm()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.rounded_l_lg()
|
||||
.when(line_count > 1, |el| el.rounded_br_lg())
|
||||
.pr_1()
|
||||
.child(styled_text),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
.h(ACCEPT_INDICATOR_HEIGHT)
|
||||
.mb(px(-1.))
|
||||
.h(line_height + BORDER_WIDTH * px(2.))
|
||||
.px_1p5()
|
||||
.gap_1()
|
||||
.shadow_sm()
|
||||
.bg(Editor::edit_prediction_line_popover_bg_color(cx))
|
||||
.border_1()
|
||||
.border_b_0()
|
||||
.border(BORDER_WIDTH)
|
||||
.border_l_0()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.rounded_t_lg()
|
||||
.rounded_r_lg()
|
||||
.children(editor.render_edit_prediction_accept_keybind(window, cx)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.bg(cx.theme().colors().editor_background)
|
||||
.border_1()
|
||||
.shadow_sm()
|
||||
.border_color(cx.theme().colors().border)
|
||||
.rounded_lg()
|
||||
.rounded_tr(Pixels::ZERO)
|
||||
.child(styled_text),
|
||||
)
|
||||
.into_any();
|
||||
|
||||
let line_count = highlighted_edits.text.lines().count();
|
||||
|
||||
let longest_row =
|
||||
editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
|
||||
let longest_line_width = if visible_row_range.contains(&longest_row) {
|
||||
@@ -3871,55 +3870,50 @@ impl EditorElement {
|
||||
|
||||
// Fully visible if it can be displayed within the window (allow overlapping other
|
||||
// panes). However, this is only allowed if the popover starts within text_bounds.
|
||||
let is_fully_visible = x_after_longest < text_bounds.right()
|
||||
let can_position_to_the_right = x_after_longest < text_bounds.right()
|
||||
&& x_after_longest + element_bounds.width < viewport_bounds.right();
|
||||
|
||||
let mut origin = if is_fully_visible {
|
||||
let mut origin = if can_position_to_the_right {
|
||||
point(
|
||||
x_after_longest,
|
||||
text_bounds.origin.y + edit_start.row().as_f32() * line_height
|
||||
- scroll_pixel_position.y,
|
||||
)
|
||||
} else {
|
||||
// Avoid overlapping both the edited rows and the user's cursor.
|
||||
let target_above = DisplayRow(
|
||||
edit_start
|
||||
.row()
|
||||
.0
|
||||
.min(
|
||||
newest_selection_head
|
||||
.map_or(u32::MAX, |cursor_row| cursor_row.row().0),
|
||||
)
|
||||
.saturating_sub(line_count as u32),
|
||||
);
|
||||
let mut row_target;
|
||||
if visible_row_range.contains(&DisplayRow(target_above.0.saturating_sub(1))) {
|
||||
row_target = target_above;
|
||||
} else {
|
||||
row_target = DisplayRow(
|
||||
edit_end.row().0.max(
|
||||
newest_selection_head.map_or(0, |cursor_row| cursor_row.row().0),
|
||||
) + 1,
|
||||
);
|
||||
if !visible_row_range.contains(&row_target) {
|
||||
// Not visible, so fallback on displaying immediately below the cursor.
|
||||
if let Some(cursor) = newest_selection_head {
|
||||
row_target = DisplayRow(cursor.row().0 + 1);
|
||||
} else {
|
||||
// Not visible and no cursor visible, so fallback on displaying at the top of the editor.
|
||||
row_target = DisplayRow(0);
|
||||
}
|
||||
}
|
||||
};
|
||||
let cursor_row = newest_selection_head.map(|head| head.row());
|
||||
let above_edit = edit_start
|
||||
.row()
|
||||
.0
|
||||
.checked_sub(line_count as u32)
|
||||
.map(DisplayRow);
|
||||
let below_edit = Some(edit_end.row() + 1);
|
||||
let above_cursor = cursor_row
|
||||
.and_then(|row| row.0.checked_sub(line_count as u32).map(DisplayRow));
|
||||
let below_cursor = cursor_row.map(|cursor_row| cursor_row + 1);
|
||||
|
||||
text_bounds.origin
|
||||
// Place the edit popover adjacent to the edit if there is a location
|
||||
// available that is onscreen and does not obscure the cursor. Otherwise,
|
||||
// place it adjacent to the cursor.
|
||||
let row_target = [above_edit, below_edit, above_cursor, below_cursor]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.find(|&start_row| {
|
||||
let end_row = start_row + line_count as u32;
|
||||
visible_row_range.contains(&start_row)
|
||||
&& visible_row_range.contains(&end_row)
|
||||
&& cursor_row.map_or(true, |cursor_row| {
|
||||
!((start_row..end_row).contains(&cursor_row))
|
||||
})
|
||||
})?;
|
||||
|
||||
content_origin
|
||||
+ point(
|
||||
-scroll_pixel_position.x,
|
||||
row_target.as_f32() * line_height - scroll_pixel_position.y,
|
||||
)
|
||||
};
|
||||
|
||||
origin.y -= ACCEPT_INDICATOR_HEIGHT;
|
||||
origin.x -= BORDER_WIDTH;
|
||||
|
||||
window.defer_draw(element, origin, 1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user