Render code actions indicator
Co-Authored-By: Nathan <nathan@zed.dev>
This commit is contained in:
parent
cfee1401ed
commit
5d15886675
8 changed files with 225 additions and 126 deletions
|
@ -40,9 +40,9 @@ use fuzzy::{StringMatch, StringMatchCandidate};
|
|||
use git::diff_hunk_to_display;
|
||||
use gpui::{
|
||||
action, actions, point, px, relative, rems, size, AnyElement, AppContext, BackgroundExecutor,
|
||||
Bounds, ClipboardItem, Context, DispatchContext, EventEmitter, FocusHandle, FontFeatures,
|
||||
FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, Model, Pixels, Render, Subscription,
|
||||
Task, TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||
Bounds, ClipboardItem, Component, Context, DispatchContext, EventEmitter, FocusHandle,
|
||||
FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, Model, Pixels, Render,
|
||||
Subscription, Task, TextStyle, View, ViewContext, VisualContext, WeakView, WindowContext,
|
||||
};
|
||||
use highlight_matching_bracket::refresh_matching_bracket_highlights;
|
||||
use hover_popover::{hide_hover, HoverState};
|
||||
|
@ -95,6 +95,7 @@ use text::{OffsetUtf16, Rope};
|
|||
use theme::{
|
||||
ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
|
||||
};
|
||||
use ui2::IconButton;
|
||||
use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
|
||||
|
@ -3846,44 +3847,44 @@ impl Editor {
|
|||
// }))
|
||||
// }
|
||||
|
||||
// pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
|
||||
// let mut context_menu = self.context_menu.write();
|
||||
// if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
|
||||
// *context_menu = None;
|
||||
// cx.notify();
|
||||
// return;
|
||||
// }
|
||||
// drop(context_menu);
|
||||
pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
|
||||
let mut context_menu = self.context_menu.write();
|
||||
if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
|
||||
*context_menu = None;
|
||||
cx.notify();
|
||||
return;
|
||||
}
|
||||
drop(context_menu);
|
||||
|
||||
// let deployed_from_indicator = action.deployed_from_indicator;
|
||||
// let mut task = self.code_actions_task.take();
|
||||
// cx.spawn(|this, mut cx| async move {
|
||||
// while let Some(prev_task) = task {
|
||||
// prev_task.await;
|
||||
// task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
|
||||
// }
|
||||
let deployed_from_indicator = action.deployed_from_indicator;
|
||||
let mut task = self.code_actions_task.take();
|
||||
cx.spawn(|this, mut cx| async move {
|
||||
while let Some(prev_task) = task {
|
||||
prev_task.await;
|
||||
task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
|
||||
}
|
||||
|
||||
// this.update(&mut cx, |this, cx| {
|
||||
// if this.focused {
|
||||
// if let Some((buffer, actions)) = this.available_code_actions.clone() {
|
||||
// this.completion_tasks.clear();
|
||||
// this.discard_copilot_suggestion(cx);
|
||||
// *this.context_menu.write() =
|
||||
// Some(ContextMenu::CodeActions(CodeActionsMenu {
|
||||
// buffer,
|
||||
// actions,
|
||||
// selected_item: Default::default(),
|
||||
// list: Default::default(),
|
||||
// deployed_from_indicator,
|
||||
// }));
|
||||
// }
|
||||
// }
|
||||
// })?;
|
||||
this.update(&mut cx, |this, cx| {
|
||||
if this.focus_handle.is_focused(cx) {
|
||||
if let Some((buffer, actions)) = this.available_code_actions.clone() {
|
||||
this.completion_tasks.clear();
|
||||
this.discard_copilot_suggestion(cx);
|
||||
*this.context_menu.write() =
|
||||
Some(ContextMenu::CodeActions(CodeActionsMenu {
|
||||
buffer,
|
||||
actions,
|
||||
selected_item: Default::default(),
|
||||
list: Default::default(),
|
||||
deployed_from_indicator,
|
||||
}));
|
||||
}
|
||||
}
|
||||
})?;
|
||||
|
||||
// Ok::<_, anyhow::Error>(())
|
||||
// })
|
||||
// .detach_and_log_err(cx);
|
||||
// }
|
||||
Ok::<_, anyhow::Error>(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
// pub fn confirm_code_action(
|
||||
// workspace: &mut Workspace,
|
||||
|
@ -4390,41 +4391,29 @@ impl Editor {
|
|||
self.discard_copilot_suggestion(cx);
|
||||
}
|
||||
|
||||
// pub fn render_code_actions_indicator(
|
||||
// &self,
|
||||
// style: &EditorStyle,
|
||||
// is_active: bool,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) -> Option<AnyElement<Self>> {
|
||||
// if self.available_code_actions.is_some() {
|
||||
// enum CodeActions {}
|
||||
// Some(
|
||||
// MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
|
||||
// Svg::new("icons/bolt.svg").with_color(
|
||||
// style
|
||||
// .code_actions
|
||||
// .indicator
|
||||
// .in_state(is_active)
|
||||
// .style_for(state)
|
||||
// .color,
|
||||
// )
|
||||
// })
|
||||
// .with_cursor_style(CursorStyle::PointingHand)
|
||||
// .with_padding(Padding::uniform(3.))
|
||||
// .on_down(MouseButton::Left, |_, this, cx| {
|
||||
// this.toggle_code_actions(
|
||||
// &ToggleCodeActions {
|
||||
// deployed_from_indicator: true,
|
||||
// },
|
||||
// cx,
|
||||
// );
|
||||
// })
|
||||
// .into_any(),
|
||||
// )
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
pub fn render_code_actions_indicator(
|
||||
&self,
|
||||
style: &EditorStyle,
|
||||
is_active: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<AnyElement<Self>> {
|
||||
if self.available_code_actions.is_some() {
|
||||
Some(
|
||||
IconButton::new("code_actions", ui2::Icon::Bolt)
|
||||
.on_click(|editor: &mut Editor, cx| {
|
||||
editor.toggle_code_actions(
|
||||
&ToggleCodeActions {
|
||||
deployed_from_indicator: true,
|
||||
},
|
||||
cx,
|
||||
);
|
||||
})
|
||||
.render(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn render_fold_indicators(
|
||||
// &self,
|
||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
|||
use anyhow::Result;
|
||||
use collections::{BTreeMap, HashMap};
|
||||
use gpui::{
|
||||
black, hsla, point, px, relative, size, transparent_black, Action, AnyElement,
|
||||
black, hsla, point, px, relative, size, transparent_black, Action, AnyElement, AvailableSpace,
|
||||
BorrowAppContext, BorrowWindow, Bounds, ContentMask, Corners, DispatchContext, DispatchPhase,
|
||||
Edges, Element, ElementId, ElementInputHandler, Entity, FocusHandle, GlobalElementId, Hsla,
|
||||
InputHandler, KeyDownEvent, KeyListener, KeyMatch, Line, LineLayout, Modifiers, MouseButton,
|
||||
|
@ -447,7 +447,7 @@ impl EditorElement {
|
|||
fn paint_gutter(
|
||||
&mut self,
|
||||
bounds: Bounds<Pixels>,
|
||||
layout: &LayoutState,
|
||||
layout: &mut LayoutState,
|
||||
editor: &mut Editor,
|
||||
cx: &mut ViewContext<Editor>,
|
||||
) {
|
||||
|
@ -495,14 +495,21 @@ impl EditorElement {
|
|||
// }
|
||||
// }
|
||||
|
||||
// todo!("code actions indicator")
|
||||
// if let Some((row, indicator)) = layout.code_actions_indicator.as_mut() {
|
||||
// let mut x = 0.;
|
||||
// let mut y = *row as f32 * line_height - scroll_top;
|
||||
// x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x) / 2.;
|
||||
// y += (line_height - indicator.size().y) / 2.;
|
||||
// indicator.paint(bounds.origin + point(x, y), visible_bounds, editor, cx);
|
||||
// }
|
||||
if let Some(indicator) = layout.code_actions_indicator.as_mut() {
|
||||
let available_space = size(
|
||||
AvailableSpace::MinContent,
|
||||
AvailableSpace::Definite(line_height),
|
||||
);
|
||||
let indicator_size = indicator.element.measure(available_space, editor, cx);
|
||||
let mut x = Pixels::ZERO;
|
||||
let mut y = indicator.row as f32 * line_height - scroll_top;
|
||||
// Center indicator.
|
||||
x += ((layout.gutter_padding + layout.gutter_margin) - indicator_size.width) / 2.;
|
||||
y += (line_height - indicator_size.height) / 2.;
|
||||
indicator
|
||||
.element
|
||||
.draw(bounds.origin + point(x, y), available_space, editor, cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn paint_diff_hunks(
|
||||
|
@ -1776,24 +1783,27 @@ impl EditorElement {
|
|||
|
||||
// todo!("context menu")
|
||||
// let mut context_menu = None;
|
||||
// let mut code_actions_indicator = None;
|
||||
// if let Some(newest_selection_head) = newest_selection_head {
|
||||
// if (start_row..end_row).contains(&newest_selection_head.row()) {
|
||||
// if editor.context_menu_visible() {
|
||||
// context_menu =
|
||||
// editor.render_context_menu(newest_selection_head, style.clone(), cx);
|
||||
// }
|
||||
let mut code_actions_indicator = None;
|
||||
if let Some(newest_selection_head) = newest_selection_head {
|
||||
if (start_row..end_row).contains(&newest_selection_head.row()) {
|
||||
// if editor.context_menu_visible() {
|
||||
// context_menu =
|
||||
// editor.render_context_menu(newest_selection_head, style.clone(), cx);
|
||||
// }
|
||||
|
||||
// let active = matches!(
|
||||
// editor.context_menu.read().as_ref(),
|
||||
// Some(crate::ContextMenu::CodeActions(_))
|
||||
// );
|
||||
let active = matches!(
|
||||
editor.context_menu.read().as_ref(),
|
||||
Some(crate::ContextMenu::CodeActions(_))
|
||||
);
|
||||
|
||||
// code_actions_indicator = editor
|
||||
// .render_code_actions_indicator(&style, active, cx)
|
||||
// .map(|indicator| (newest_selection_head.row(), indicator));
|
||||
// }
|
||||
// }
|
||||
code_actions_indicator = editor
|
||||
.render_code_actions_indicator(&style, active, cx)
|
||||
.map(|element| CodeActionsIndicator {
|
||||
row: newest_selection_head.row(),
|
||||
element,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let visible_rows = start_row..start_row + line_layouts.len() as u32;
|
||||
// todo!("hover")
|
||||
|
@ -1831,18 +1841,6 @@ impl EditorElement {
|
|||
// );
|
||||
// }
|
||||
|
||||
// todo!("code actions")
|
||||
// if let Some((_, indicator)) = code_actions_indicator.as_mut() {
|
||||
// indicator.layout(
|
||||
// SizeConstraint::strict_along(
|
||||
// Axis::Vertical,
|
||||
// line_height * style.code_actions.vertical_scale,
|
||||
// ),
|
||||
// editor,
|
||||
// cx,
|
||||
// );
|
||||
// }
|
||||
|
||||
// todo!("fold indicators")
|
||||
// for fold_indicator in fold_indicators.iter_mut() {
|
||||
// if let Some(indicator) = fold_indicator.as_mut() {
|
||||
|
@ -1942,7 +1940,7 @@ impl EditorElement {
|
|||
// blocks,
|
||||
selections,
|
||||
// context_menu,
|
||||
// code_actions_indicator,
|
||||
code_actions_indicator,
|
||||
// fold_indicators,
|
||||
tab_invisible,
|
||||
space_invisible,
|
||||
|
@ -2493,7 +2491,7 @@ impl Element<Editor> for EditorElement {
|
|||
element_state: &mut Self::ElementState,
|
||||
cx: &mut gpui::ViewContext<Editor>,
|
||||
) {
|
||||
let layout = self.compute_layout(editor, cx, bounds);
|
||||
let mut layout = self.compute_layout(editor, cx, bounds);
|
||||
let gutter_bounds = Bounds {
|
||||
origin: bounds.origin,
|
||||
size: layout.gutter_size,
|
||||
|
@ -2513,7 +2511,7 @@ impl Element<Editor> for EditorElement {
|
|||
);
|
||||
self.paint_background(gutter_bounds, text_bounds, &layout, cx);
|
||||
if layout.gutter_size.width > Pixels::ZERO {
|
||||
self.paint_gutter(gutter_bounds, &layout, editor, cx);
|
||||
self.paint_gutter(gutter_bounds, &mut layout, editor, cx);
|
||||
}
|
||||
self.paint_text(text_bounds, &layout, editor, cx);
|
||||
let input_handler = ElementInputHandler::new(bounds, cx);
|
||||
|
@ -3144,13 +3142,18 @@ pub struct LayoutState {
|
|||
is_singleton: bool,
|
||||
max_row: u32,
|
||||
// context_menu: Option<(DisplayPoint, AnyElement<Editor>)>,
|
||||
// code_actions_indicator: Option<(u32, AnyElement<Editor>)>,
|
||||
code_actions_indicator: Option<CodeActionsIndicator>,
|
||||
// hover_popovers: Option<(DisplayPoint, Vec<AnyElement<Editor>>)>,
|
||||
// fold_indicators: Vec<Option<AnyElement<Editor>>>,
|
||||
tab_invisible: Line,
|
||||
space_invisible: Line,
|
||||
}
|
||||
|
||||
struct CodeActionsIndicator {
|
||||
row: u32,
|
||||
element: AnyElement<Editor>,
|
||||
}
|
||||
|
||||
struct PositionMap {
|
||||
size: Size<Pixels>,
|
||||
line_height: Pixels,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue