This commit is contained in:
Nathan Sobo 2023-04-12 06:51:03 -06:00
parent d9e4136b02
commit b54f08db77
22 changed files with 374 additions and 300 deletions

View file

@ -2,7 +2,7 @@ use super::{
wrap_map::{self, WrapEdit, WrapPoint, WrapSnapshot},
TextHighlights,
};
use crate::{Anchor, ExcerptId, ExcerptRange, ToPoint as _};
use crate::{Anchor, Editor, ExcerptId, ExcerptRange, ToPoint as _};
use collections::{Bound, HashMap, HashSet};
use gpui::{fonts::HighlightStyle, ElementBox, ViewContext};
use language::{BufferSnapshot, Chunk, Patch, Point};
@ -50,7 +50,7 @@ struct BlockRow(u32);
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
struct WrapRow(u32);
pub type RenderBlock = Arc<dyn Fn(&mut BlockContext) -> ElementBox>;
pub type RenderBlock = Arc<dyn Fn(&mut BlockContext) -> ElementBox<Editor>>;
pub struct Block {
id: BlockId,
@ -69,7 +69,7 @@ where
pub position: P,
pub height: u8,
pub style: BlockStyle,
pub render: Arc<dyn Fn(&mut BlockContext) -> ElementBox>,
pub render: Arc<dyn Fn(&mut BlockContext) -> ElementBox<Editor>>,
pub disposition: BlockDisposition,
}
@ -80,8 +80,8 @@ pub enum BlockStyle {
Sticky,
}
pub struct BlockContext<'a, 'b> {
pub cx: &'b mut ViewContext<'a, crate::Editor>,
pub struct BlockContext<'a, 'b, 'c, 'd> {
pub view_context: &'d mut ViewContext<'a, 'b, 'c, Editor>,
pub anchor_x: f32,
pub scroll_x: f32,
pub gutter_width: f32,
@ -932,22 +932,22 @@ impl BlockDisposition {
}
}
impl<'a, 'b> Deref for BlockContext<'a, 'b> {
type Target = ViewContext<'a, crate::Editor>;
impl<'a, 'b, 'c, 'd> Deref for BlockContext<'a, 'b, 'c, 'd> {
type Target = ViewContext<'a, 'b, 'c, Editor>;
fn deref(&self) -> &Self::Target {
self.cx
self.view_context
}
}
impl<'a, 'b> DerefMut for BlockContext<'a, 'b> {
impl DerefMut for BlockContext<'_, '_, '_, '_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.cx
self.view_context
}
}
impl Block {
pub fn render(&self, cx: &mut BlockContext) -> ElementBox {
pub fn render(&self, cx: &mut BlockContext) -> ElementBox<Editor> {
self.render.lock()(cx)
}

View file

@ -722,7 +722,7 @@ impl ContextMenu {
cursor_position: DisplayPoint,
style: EditorStyle,
cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, ElementBox) {
) -> (DisplayPoint, ElementBox<Editor>) {
match self {
ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
@ -774,7 +774,7 @@ impl CompletionsMenu {
!self.matches.is_empty()
}
fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox<Editor> {
enum CompletionTag {}
let completions = self.completions.clone();
@ -791,7 +791,7 @@ impl CompletionsMenu {
let completion = &completions[mat.candidate_id];
let item_ix = start_ix + ix;
items.push(
MouseEventHandler::<CompletionTag>::new(
MouseEventHandler::<CompletionTag, _>::new(
mat.candidate_id,
cx,
|state, _| {
@ -820,7 +820,7 @@ impl CompletionsMenu {
},
)
.with_cursor_style(CursorStyle::PointingHand)
.on_down(MouseButton::Left, move |_, cx| {
.on_down(MouseButton::Left, move |_, _, cx| {
cx.dispatch_action(ConfirmCompletion {
item_ix: Some(item_ix),
});
@ -951,7 +951,7 @@ impl CodeActionsMenu {
mut cursor_position: DisplayPoint,
style: EditorStyle,
cx: &mut ViewContext<Editor>,
) -> (DisplayPoint, ElementBox) {
) -> (DisplayPoint, ElementBox<Editor>) {
enum ActionTag {}
let container_style = style.autocomplete.container;
@ -966,7 +966,7 @@ impl CodeActionsMenu {
for (ix, action) in actions[range].iter().enumerate() {
let item_ix = start_ix + ix;
items.push(
MouseEventHandler::<ActionTag>::new(item_ix, cx, |state, _| {
MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| {
let item_style = if item_ix == selected_item {
style.autocomplete.selected_item
} else if state.hovered() {
@ -982,7 +982,7 @@ impl CodeActionsMenu {
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_down(MouseButton::Left, move |_, cx| {
.on_down(MouseButton::Left, move |_, _, cx| {
cx.dispatch_action(ConfirmCodeAction {
item_ix: Some(item_ix),
});
@ -2929,18 +2929,18 @@ impl Editor {
style: &EditorStyle,
active: bool,
cx: &mut ViewContext<Self>,
) -> Option<ElementBox> {
) -> Option<ElementBox<Self>> {
if self.available_code_actions.is_some() {
enum CodeActions {}
Some(
MouseEventHandler::<CodeActions>::new(0, cx, |state, _| {
MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
Svg::new("icons/bolt_8.svg")
.with_color(style.code_actions.indicator.style_for(state, active).color)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.with_padding(Padding::uniform(3.))
.on_down(MouseButton::Left, |_, cx| {
.on_down(MouseButton::Left, |_, _, cx| {
cx.dispatch_action(ToggleCodeActions {
deployed_from_indicator: true,
});
@ -2960,7 +2960,7 @@ impl Editor {
line_height: f32,
gutter_margin: f32,
cx: &mut ViewContext<Self>,
) -> Vec<Option<ElementBox>> {
) -> Vec<Option<ElementBox<Self>>> {
enum FoldIndicators {}
let style = style.folds.clone();
@ -2972,10 +2972,10 @@ impl Editor {
fold_data
.map(|(fold_status, buffer_row, active)| {
(active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
MouseEventHandler::<FoldIndicators>::new(
MouseEventHandler::<FoldIndicators, _>::new(
ix as usize,
cx,
|mouse_state, _| -> ElementBox {
|mouse_state, _| -> ElementBox<Editor> {
Svg::new(match fold_status {
FoldStatus::Folded => style.folded_icon.clone(),
FoldStatus::Foldable => style.foldable_icon.clone(),
@ -3002,7 +3002,7 @@ impl Editor {
.with_cursor_style(CursorStyle::PointingHand)
.with_padding(Padding::uniform(3.))
.on_click(MouseButton::Left, {
move |_, cx| {
move |_, _, cx| {
cx.dispatch_any_action(match fold_status {
FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
@ -3028,7 +3028,7 @@ impl Editor {
cursor_position: DisplayPoint,
style: EditorStyle,
cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, ElementBox)> {
) -> Option<(DisplayPoint, ElementBox<Editor>)> {
self.context_menu
.as_ref()
.map(|menu| menu.render(cursor_position, style, cx))
@ -3911,7 +3911,7 @@ impl Editor {
pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
self.transact(cx, |this, cx| {
if let Some(item) = cx.as_mut().read_from_clipboard() {
if let Some(item) = cx.read_from_clipboard() {
let mut clipboard_text = Cow::Borrowed(item.text());
if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
let old_selections = this.selections.all::<usize>(cx);
@ -5793,7 +5793,7 @@ impl Editor {
self.pending_rename.as_ref()
}
fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
let project = match &self.project {
Some(project) => project.clone(),
None => return None,
@ -5806,7 +5806,7 @@ impl Editor {
&mut self,
project: ModelHandle<Project>,
trigger: FormatTrigger,
cx: &mut ViewContext<'_, Self>,
cx: &mut ViewContext<Self>,
) -> Task<Result<()>> {
let buffer = self.buffer().clone();
let buffers = buffer.read(cx).all_buffers();
@ -6795,7 +6795,7 @@ impl Entity for Editor {
}
impl View for Editor {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> {
let style = self.style(cx);
let font_changed = self.display_map.update(cx, |map, cx| {
map.set_fold_ellipses_color(style.folds.ellipses.text_color);
@ -6804,7 +6804,7 @@ impl View for Editor {
if font_changed {
let handle = self.handle.clone();
cx.defer(move |cx: &mut ViewContext<Editor>| {
cx.defer(move |_, cx: &mut ViewContext<Editor>| {
if let Some(editor) = handle.upgrade(cx) {
editor.update(cx, |editor, cx| {
hide_hover(editor, &HideHover, cx);

View file

@ -31,8 +31,8 @@ use gpui::{
json::{self, ToJson},
platform::{CursorStyle, Modifiers, MouseButton, MouseButtonEvent, MouseMovedEvent},
text_layout::{self, Line, RunStyle, TextLayoutCache},
AppContext, Axis, Border, CursorRegion, Element, ElementBox, MouseRegion, Quad, SceneBuilder,
SizeConstraint, ViewContext, WeakViewHandle,
AppContext, Axis, Border, CursorRegion, Element, ElementBox, EventContext, MouseRegion, Quad,
SceneBuilder, SizeConstraint, ViewContext, WeakViewHandle, WindowContext,
};
use itertools::Itertools;
use json::json;
@ -98,10 +98,6 @@ impl EditorElement {
}
}
fn view<'a>(&self, cx: &'a AppContext) -> &'a Editor {
self.view.upgrade(cx).unwrap().read(cx)
}
fn update_view<F, T>(&self, cx: &mut AppContext, f: F) -> T
where
F: FnOnce(&mut Editor, &mut ViewContext<Editor>) -> T,
@ -114,6 +110,7 @@ impl EditorElement {
}
fn attach_mouse_handlers(
scene: &mut SceneBuilder,
view: &WeakViewHandle<Editor>,
position_map: &Arc<PositionMap>,
has_popovers: bool,
@ -121,14 +118,14 @@ impl EditorElement {
text_bounds: RectF,
gutter_bounds: RectF,
bounds: RectF,
cx: &mut PaintContext,
cx: &mut ViewContext<Editor>,
) {
enum EditorElementMouseHandlers {}
scene.push_mouse_region(
MouseRegion::new::<EditorElementMouseHandlers>(view.id(), view.id(), visible_bounds)
.on_down(MouseButton::Left, {
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::mouse_down(
e.platform_event,
position_map.as_ref(),
@ -142,7 +139,7 @@ impl EditorElement {
})
.on_down(MouseButton::Right, {
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::mouse_right_down(
e.position,
position_map.as_ref(),
@ -156,7 +153,7 @@ impl EditorElement {
.on_up(MouseButton::Left, {
let view = view.clone();
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::mouse_up(
view.clone(),
e.position,
@ -173,7 +170,7 @@ impl EditorElement {
.on_drag(MouseButton::Left, {
let view = view.clone();
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::mouse_dragged(
view.clone(),
e.platform_event,
@ -187,20 +184,20 @@ impl EditorElement {
})
.on_move({
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::mouse_moved(e.platform_event, &position_map, text_bounds, cx) {
cx.propagate_event()
}
}
})
.on_move_out(move |_, cx| {
.on_move_out(move |_, _: &mut Editor, cx| {
if has_popovers {
cx.dispatch_action(HideHover);
}
})
.on_scroll({
let position_map = position_map.clone();
move |e, cx| {
move |e, _, cx| {
if !Self::scroll(
e.position,
*e.delta.raw(),
@ -218,7 +215,7 @@ impl EditorElement {
enum GutterHandlers {}
scene.push_mouse_region(
MouseRegion::new::<GutterHandlers>(view.id(), view.id() + 1, gutter_bounds).on_hover(
|hover, cx| {
|hover, _: &mut Editor, cx| {
cx.dispatch_action(GutterHover {
hovered: hover.started,
})
@ -244,7 +241,7 @@ impl EditorElement {
position_map: &PositionMap,
text_bounds: RectF,
gutter_bounds: RectF,
cx: &mut EventContext,
cx: &mut EventContext<Editor>,
) -> bool {
if gutter_bounds.contains_point(position) {
click_count = 3; // Simulate triple-click when clicking the gutter to select lines
@ -279,7 +276,7 @@ impl EditorElement {
position: Vector2F,
position_map: &PositionMap,
text_bounds: RectF,
cx: &mut EventContext,
cx: &mut EventContext<Editor>,
) -> bool {
if !text_bounds.contains_point(position) {
return false;
@ -298,9 +295,9 @@ impl EditorElement {
shift: bool,
position_map: &PositionMap,
text_bounds: RectF,
cx: &mut EventContext,
cx: &mut EventContext<Editor>,
) -> bool {
let view = view.upgrade(cx.app).unwrap().read(cx.app);
let view = view.upgrade(cx).unwrap().read(cx);
let end_selection = view.has_pending_selection();
let pending_nonempty_selections = view.has_pending_nonempty_selection();
@ -334,7 +331,7 @@ impl EditorElement {
}: MouseMovedEvent,
position_map: &PositionMap,
text_bounds: RectF,
cx: &mut EventContext,
cx: &mut EventContext<Editor>,
) -> bool {
// This will be handled more correctly once https://github.com/zed-industries/zed/issues/1218 is completed
// Don't trigger hover popover if mouse is hovering over context menu
@ -355,7 +352,7 @@ impl EditorElement {
shift_held: shift,
});
let view = view.upgrade(cx.app).unwrap().read(cx.app);
let view = view.upgrade(cx).unwrap().read(cx);
if view.has_pending_selection() {
let mut scroll_delta = Vector2F::zero();
@ -480,7 +477,7 @@ impl EditorElement {
border: Border::new(0., Color::transparent_black()),
corner_radius: 0.,
});
c.push_quad(Quad {
scene.push_quad(Quad {
bounds: text_bounds,
background: Some(self.style.background),
border: Border::new(0., Color::transparent_black()),
@ -545,7 +542,7 @@ impl EditorElement {
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
cx: &mut ViewContext<Editor>,
) {
let line_height = layout.position_map.line_height;
@ -561,7 +558,7 @@ impl EditorElement {
);
if show_gutter {
Self::paint_diff_hunks(bounds, layout, cx);
Self::paint_diff_hunks(scene, bounds, layout, cx);
}
for (ix, line) in layout.line_number_layouts.iter().enumerate() {
@ -608,7 +605,12 @@ impl EditorElement {
}
}
fn paint_diff_hunks(bounds: RectF, layout: &mut LayoutState, cx: &mut PaintContext) {
fn paint_diff_hunks(
scene: &mut SceneBuilder,
bounds: RectF,
layout: &mut LayoutState,
cx: &mut ViewContext<Editor>,
) {
let diff_style = &cx.global::<Settings>().theme.editor.diff.clone();
let line_height = layout.position_map.line_height;
@ -698,11 +700,10 @@ impl EditorElement {
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
cx: &mut ViewContext<Editor>,
) {
let view = self.view(cx.app);
let style = &self.style;
let local_replica_id = view.replica_id(cx);
let local_replica_id = editor.replica_id(cx);
let scroll_position = layout.position_map.snapshot.scroll_position();
let start_row = layout.visible_display_row_range.start;
let scroll_top = scroll_position.y() * layout.position_map.line_height;
@ -715,7 +716,7 @@ impl EditorElement {
scene.push_cursor_region(CursorRegion {
bounds,
style: if !view.link_go_to_definition_state.definitions.is_empty() {
style: if !editor.link_go_to_definition_state.definitions.is_empty() {
CursorStyle::PointingHand
} else {
CursorStyle::IBeam
@ -761,7 +762,7 @@ impl EditorElement {
scene.push_mouse_region(
MouseRegion::new::<FoldMarkers>(self.view.id(), *id as usize, bound)
.on_click(MouseButton::Left, move |_, cx| {
.on_click(MouseButton::Left, move |_, _: &mut Editor, cx| {
cx.dispatch_action(UnfoldAt { buffer_row })
})
.with_notify_on_hover(true)
@ -807,7 +808,7 @@ impl EditorElement {
cx,
);
if view.show_local_cursors(cx) || *replica_id != local_replica_id {
if editor.show_local_cursors(cx) || *replica_id != local_replica_id {
let cursor_position = selection.head;
if layout
.visible_display_row_range
@ -834,7 +835,7 @@ impl EditorElement {
cursor_row_layout.font_for_index(cursor_column)?;
let text = character.to_string();
Some(cx.text_layout_cache.layout_str(
Some(cx.text_layout_cache().layout_str(
&text,
cursor_row_layout.font_size(),
&[(
@ -905,8 +906,8 @@ impl EditorElement {
// Snap the right edge of the list to the right edge of the window if
// its horizontal bounds overflow.
if list_origin.x() + list_width > cx.window_size.x() {
list_origin.set_x((cx.window_size.x() - list_width).max(0.));
if list_origin.x() + list_width > cx.window_size().x() {
list_origin.set_x((cx.window_size().x() - list_width).max(0.));
}
if list_origin.y() + list_height > bounds.max_y() {
@ -1059,7 +1060,7 @@ impl EditorElement {
MouseRegion::new::<ScrollbarMouseHandlers>(view.id(), view.id(), track_bounds)
.on_move({
let view = view.clone();
move |_, cx| {
move |_, _: &mut Editor, cx| {
if let Some(view) = view.upgrade(cx.deref_mut()) {
view.update(cx.deref_mut(), |view, cx| {
view.scroll_manager.show_scrollbar(cx);
@ -1070,7 +1071,7 @@ impl EditorElement {
.on_down(MouseButton::Left, {
let view = view.clone();
let row_range = row_range.clone();
move |e, cx| {
move |e, _: &mut Editor, cx| {
let y = e.position.y();
if let Some(view) = view.upgrade(cx.deref_mut()) {
view.update(cx.deref_mut(), |view, cx| {
@ -1092,7 +1093,7 @@ impl EditorElement {
})
.on_drag(MouseButton::Left, {
let view = view.clone();
move |e, cx| {
move |e, _: &mut Editor, cx| {
let y = e.prev_mouse_position.y();
let new_y = e.position.y();
if thumb_top < y && y < thumb_bottom {
@ -1127,7 +1128,7 @@ impl EditorElement {
scroll_top: f32,
scroll_left: f32,
bounds: RectF,
cx: &mut ViewContext<Self>,
cx: &mut ViewContext<Editor>,
) {
let start_row = layout.visible_display_row_range.start;
let end_row = layout.visible_display_row_range.end;
@ -1182,7 +1183,7 @@ impl EditorElement {
visible_bounds: RectF,
layout: &mut LayoutState,
editor: &mut Editor,
cx: &mut PaintContext,
cx: &mut ViewContext<Editor>,
) {
let scroll_position = layout.position_map.snapshot.scroll_position();
let scroll_left = scroll_position.x() * layout.position_map.em_width;
@ -1203,11 +1204,11 @@ impl EditorElement {
}
}
fn max_line_number_width(&self, snapshot: &EditorSnapshot, cx: &LayoutContext) -> f32 {
fn max_line_number_width(&self, snapshot: &EditorSnapshot, cx: &ViewContext<Editor>) -> f32 {
let digit_count = (snapshot.max_buffer_row() as f32).log10().floor() as usize + 1;
let style = &self.style;
cx.text_layout_cache
cx.text_layout_cache()
.layout_str(
"1".repeat(digit_count).as_str(),
style.text.font_size,
@ -1252,7 +1253,7 @@ impl EditorElement {
active_rows: &BTreeMap<u32, bool>,
is_singleton: bool,
snapshot: &EditorSnapshot,
cx: &LayoutContext,
cx: &ViewContext<Editor>,
) -> (
Vec<Option<text_layout::Line>>,
Vec<Option<(FoldStatus, BufferRow, bool)>>,
@ -1277,7 +1278,7 @@ impl EditorElement {
if include_line_numbers {
line_number.clear();
write!(&mut line_number, "{}", buffer_row + 1).unwrap();
line_number_layouts.push(Some(cx.text_layout_cache.layout_str(
line_number_layouts.push(Some(cx.text_layout_cache().layout_str(
&line_number,
style.text.font_size,
&[(
@ -1312,7 +1313,7 @@ impl EditorElement {
&mut self,
rows: Range<u32>,
snapshot: &EditorSnapshot,
cx: &LayoutContext,
cx: &ViewContext<Editor>,
) -> Vec<text_layout::Line> {
if rows.start >= rows.end {
return Vec::new();
@ -1335,7 +1336,7 @@ impl EditorElement {
.take(rows.len());
placeholder_lines
.map(|line| {
cx.text_layout_cache.layout_str(
cx.text_layout_cache().layout_str(
line,
placeholder_style.font_size,
&[(
@ -1395,8 +1396,8 @@ impl EditorElement {
layout_highlighted_chunks(
chunks,
&style.text,
cx.text_layout_cache,
cx.font_cache,
cx.text_layout_cache(),
cx.font_cache(),
MAX_LINE_LEN,
rows.len() as usize,
)
@ -1419,7 +1420,7 @@ impl EditorElement {
line_layouts: &[text_layout::Line],
include_root: bool,
editor: &mut Editor,
cx: &mut LayoutContext,
cx: &mut ViewContext<Editor>,
) -> (f32, Vec<BlockLayout>) {
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
let scroll_x = snapshot.scroll_anchor.offset.x();
@ -1441,20 +1442,18 @@ impl EditorElement {
line_layouts[(align_to.row() - rows.start) as usize]
.x_for_index(align_to.column() as usize)
} else {
layout_line(align_to.row(), snapshot, style, cx.text_layout_cache)
layout_line(align_to.row(), snapshot, style, cx.text_layout_cache())
.x_for_index(align_to.column() as usize)
};
cx.render(&editor, |_, cx| {
block.render(&mut BlockContext {
cx,
anchor_x,
gutter_padding,
line_height,
scroll_x,
gutter_width,
em_width,
})
block.render(&mut BlockContext {
view_context: cx,
anchor_x,
gutter_padding,
line_height,
scroll_x,
gutter_width,
em_width,
})
}
TransformBlock::ExcerptHeader {
@ -1480,36 +1479,34 @@ impl EditorElement {
};
enum JumpIcon {}
cx.render(&editor, |_, cx| {
MouseEventHandler::<JumpIcon>::new(id.into(), cx, |state, _| {
let style = style.jump_icon.style_for(state, false);
Svg::new("icons/arrow_up_right_8.svg")
.with_color(style.color)
.constrained()
.with_width(style.icon_width)
.aligned()
.contained()
.with_style(style.container)
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, cx| {
cx.dispatch_action(jump_action.clone())
})
.with_tooltip::<JumpIcon, _>(
id.into(),
"Jump to Buffer".to_string(),
Some(Box::new(crate::OpenExcerpts)),
tooltip_style.clone(),
cx,
)
.aligned()
.flex_float()
.boxed()
MouseEventHandler::<JumpIcon, _>::new(id.into(), cx, |state, _| {
let style = style.jump_icon.style_for(state, false);
Svg::new("icons/arrow_up_right_8.svg")
.with_color(style.color)
.constrained()
.with_width(style.icon_width)
.aligned()
.contained()
.with_style(style.container)
.constrained()
.with_width(style.button_width)
.with_height(style.button_width)
.boxed()
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, _, cx| {
cx.dispatch_action(jump_action.clone())
})
.with_tooltip::<JumpIcon>(
id.into(),
"Jump to Buffer".to_string(),
Some(Box::new(crate::OpenExcerpts)),
tooltip_style.clone(),
cx,
)
.aligned()
.flex_float()
.boxed()
});
if *starts_new_buffer {
@ -1614,31 +1611,32 @@ impl EditorElement {
}
}
impl Element for EditorElement {
impl Element<Editor> for EditorElement {
type LayoutState = LayoutState;
type PaintState = ();
fn layout(
&mut self,
constraint: SizeConstraint,
cx: &mut LayoutContext,
editor: &mut Editor,
cx: &mut ViewContext<Editor>,
) -> (Vector2F, Self::LayoutState) {
let mut size = constraint.max;
if size.x().is_infinite() {
unimplemented!("we don't yet handle an infinite width constraint on buffer elements");
}
let snapshot = self.snapshot(cx.app);
let snapshot = self.snapshot(cx);
let style = self.style.clone();
let line_height = style.text.line_height(cx.font_cache);
let line_height = style.text.line_height(cx.font_cache());
let gutter_padding;
let gutter_width;
let gutter_margin;
if snapshot.mode == EditorMode::Full {
gutter_padding = style.text.em_width(cx.font_cache) * style.gutter_padding_factor;
gutter_padding = style.text.em_width(cx.font_cache()) * style.gutter_padding_factor;
gutter_width = self.max_line_number_width(&snapshot, cx) + gutter_padding * 2.0;
gutter_margin = -style.text.descent(cx.font_cache);
gutter_margin = -style.text.descent(cx.font_cache());
} else {
gutter_padding = 0.0;
gutter_width = 0.0;
@ -1646,10 +1644,10 @@ impl Element for EditorElement {
};
let text_width = size.x() - gutter_width;
let em_width = style.text.em_width(cx.font_cache);
let em_advance = style.text.em_advance(cx.font_cache);
let em_width = style.text.em_width(cx.font_cache());
let em_advance = style.text.em_advance(cx.font_cache());
let overscroll = vec2f(em_width, 0.);
let snapshot = self.update_view(cx.app, |view, cx| {
let snapshot = self.update_view(cx, |view, cx| {
view.set_visible_line_count(size.y() / line_height);
let editor_width = text_width - gutter_margin - overscroll.x() - em_width;
@ -1686,7 +1684,7 @@ impl Element for EditorElement {
let gutter_size = vec2f(gutter_width, size.y());
let text_size = vec2f(text_width, size.y());
let (autoscroll_horizontally, mut snapshot) = self.update_view(cx.app, |view, cx| {
let (autoscroll_horizontally, mut snapshot) = self.update_view(cx, |view, cx| {
let autoscroll_horizontally = view.autoscroll_vertically(size.y(), line_height, cx);
let snapshot = view.snapshot(cx);
(autoscroll_horizontally, snapshot)
@ -1728,7 +1726,7 @@ impl Element for EditorElement {
let mut show_scrollbars = false;
let mut include_root = false;
let mut is_singleton = false;
self.update_view(cx.app, |view, cx| {
self.update_view(cx, |view, cx| {
is_singleton = view.is_singleton(cx);
let display_map = view.display_map.update(cx, |map, cx| map.snapshot(cx));
@ -1859,11 +1857,11 @@ impl Element for EditorElement {
snapshot.longest_row(),
&snapshot,
&style,
cx.text_layout_cache,
cx.text_layout_cache(),
)
.width();
let scroll_width = longest_line_width.max(max_visible_line_width) + overscroll.x();
let em_width = style.text.em_width(cx.font_cache);
let em_width = style.text.em_width(cx.font_cache());
let (scroll_width, blocks) = self.layout_blocks(
start_row..end_row,
&snapshot,
@ -1886,7 +1884,7 @@ impl Element for EditorElement {
max_row as f32,
);
self.update_view(cx.app, |view, cx| {
self.update_view(cx, |view, cx| {
let clamped = view.scroll_manager.clamp_scroll_left(scroll_max.x());
let autoscrolled = if autoscroll_horizontally {
@ -1911,47 +1909,52 @@ impl Element for EditorElement {
let mut code_actions_indicator = None;
let mut hover = None;
let mut mode = EditorMode::Full;
let mut fold_indicators = cx.render(&self.view.upgrade(cx).unwrap(), |view, cx| {
let newest_selection_head = view
let mut fold_indicators = {
let newest_selection_head = editor
.selections
.newest::<usize>(cx)
.head()
.to_display_point(&snapshot);
let style = view.style(cx);
let style = editor.style(cx);
if (start_row..end_row).contains(&newest_selection_head.row()) {
if view.context_menu_visible() {
if editor.context_menu_visible() {
context_menu =
view.render_context_menu(newest_selection_head, style.clone(), cx);
editor.render_context_menu(newest_selection_head, style.clone(), cx);
}
let active = matches!(view.context_menu, Some(crate::ContextMenu::CodeActions(_)));
let active = matches!(
editor.context_menu,
Some(crate::ContextMenu::CodeActions(_))
);
code_actions_indicator = view
code_actions_indicator = editor
.render_code_actions_indicator(&style, active, cx)
.map(|indicator| (newest_selection_head.row(), indicator));
}
let visible_rows = start_row..start_row + line_layouts.len() as u32;
hover = view.hover_state.render(&snapshot, &style, visible_rows, cx);
mode = view.mode;
hover = editor
.hover_state
.render(&snapshot, &style, visible_rows, cx);
mode = editor.mode;
view.render_fold_indicators(
editor.render_fold_indicators(
fold_statuses,
&style,
view.gutter_hovered,
editor.gutter_hovered,
line_height,
gutter_margin,
cx,
)
});
};
if let Some((_, context_menu)) = context_menu.as_mut() {
context_menu.layout(
SizeConstraint {
min: Vector2F::zero(),
max: vec2f(
cx.window_size.x() * 0.7,
cx.window_size().x() * 0.7,
(12. * line_height).min((size.y() - line_height) / 2.),
),
},
@ -1978,6 +1981,7 @@ impl Element for EditorElement {
Axis::Vertical,
line_height * style.code_actions.vertical_scale,
),
editor,
cx,
);
}
@ -1997,6 +2001,7 @@ impl Element for EditorElement {
.max(MIN_POPOVER_LINE_HEIGHT * line_height), // Apply minimum height of 4 lines
),
},
editor,
cx,
);
}
@ -2041,10 +2046,12 @@ impl Element for EditorElement {
fn paint(
&mut self,
scene: &mut SceneBuilder,
bounds: RectF,
visible_bounds: RectF,
layout: &mut Self::LayoutState,
cx: &mut PaintContext,
editor: &mut Editor,
cx: &mut ViewContext<Editor>,
) -> Self::PaintState {
let visible_bounds = bounds.intersection(visible_bounds).unwrap_or_default();
scene.push_layer(Some(visible_bounds));
@ -2056,6 +2063,7 @@ impl Element for EditorElement {
);
Self::attach_mouse_handlers(
scene,
&self.view,
&layout.position_map,
layout.hover_popovers.is_some(),
@ -2089,7 +2097,8 @@ impl Element for EditorElement {
_: RectF,
layout: &Self::LayoutState,
_: &Self::PaintState,
_: &gpui::MeasurementContext,
_: &Editor,
_: &ViewContext<Editor>,
) -> Option<RectF> {
let text_bounds = RectF::new(
bounds.origin() + vec2f(layout.gutter_size.x(), 0.0),
@ -2132,7 +2141,8 @@ impl Element for EditorElement {
bounds: RectF,
_: &Self::LayoutState,
_: &Self::PaintState,
_: &gpui::DebugContext,
_: &Editor,
_: &ViewContext<Editor>,
) -> json::Value {
json!({
"type": "BufferElement",
@ -2162,10 +2172,10 @@ pub struct LayoutState {
scrollbar_row_range: Range<f32>,
show_scrollbars: bool,
max_row: u32,
context_menu: Option<(DisplayPoint, ElementBox)>,
code_actions_indicator: Option<(u32, ElementBox)>,
hover_popovers: Option<(DisplayPoint, Vec<ElementBox>)>,
fold_indicators: Vec<Option<ElementBox>>,
context_menu: Option<(DisplayPoint, ElementBox<Editor>)>,
code_actions_indicator: Option<(u32, ElementBox<Editor>)>,
hover_popovers: Option<(DisplayPoint, Vec<ElementBox<Editor>>)>,
fold_indicators: Vec<Option<ElementBox<Editor>>>,
}
pub struct PositionMap {
@ -2216,7 +2226,7 @@ impl PositionMap {
struct BlockLayout {
row: u32,
element: ElementBox,
element: ElementBox<Editor>,
style: BlockStyle,
}
@ -2287,7 +2297,7 @@ impl Cursor {
)
}
pub fn paint(&self, scene: &mut SceneBuilder, origin: Vector2F, cx: &mut AppContext) {
pub fn paint(&self, scene: &mut SceneBuilder, origin: Vector2F, cx: &mut WindowContext) {
let bounds = match self.shape {
CursorShape::Bar => RectF::new(self.origin + origin, vec2f(2.0, self.line_height)),
CursorShape::Block | CursorShape::Hollow => RectF::new(

View file

@ -283,7 +283,7 @@ impl HoverState {
style: &EditorStyle,
visible_rows: Range<u32>,
cx: &mut ViewContext<Editor>,
) -> Option<(DisplayPoint, Vec<ElementBox>)> {
) -> Option<(DisplayPoint, Vec<ElementBox<Editor>>)> {
// If there is a diagnostic, position the popovers based on that.
// Otherwise use the start of the hover range
let anchor = self
@ -323,9 +323,9 @@ pub struct InfoPopover {
}
impl InfoPopover {
pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
MouseEventHandler::<InfoPopover>::new(0, cx, |_, cx| {
let mut flex = Flex::new(Axis::Vertical).scrollable::<HoverBlock, _>(1, None, cx);
pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox<Editor> {
MouseEventHandler::<InfoPopover, _>::new(0, cx, |_, cx| {
let mut flex = Flex::new(Axis::Vertical).scrollable::<HoverBlock>(1, None, cx);
flex.extend(self.contents.iter().map(|content| {
let languages = self.project.read(cx).languages();
if let Some(language) = content.language.clone().and_then(|language| {
@ -360,7 +360,7 @@ impl InfoPopover {
.with_style(style.hover_popover.container)
.boxed()
})
.on_move(|_, _| {}) // Consume move events so they don't reach regions underneath.
.on_move(|_, _, _| {}) // Consume move events so they don't reach regions underneath.
.with_cursor_style(CursorStyle::Arrow)
.with_padding(Padding {
bottom: HOVER_POPOVER_GAP,
@ -378,7 +378,7 @@ pub struct DiagnosticPopover {
}
impl DiagnosticPopover {
pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox {
pub fn render(&self, style: &EditorStyle, cx: &mut ViewContext<Editor>) -> ElementBox<Editor> {
enum PrimaryDiagnostic {}
let mut text_style = style.hover_popover.prose.clone();
@ -394,7 +394,7 @@ impl DiagnosticPopover {
let tooltip_style = cx.global::<Settings>().theme.tooltip.clone();
MouseEventHandler::<DiagnosticPopover>::new(0, cx, |_, _| {
MouseEventHandler::<DiagnosticPopover, _>::new(0, cx, |_, _| {
Text::new(self.local_diagnostic.diagnostic.message.clone(), text_style)
.with_soft_wrap(true)
.contained()
@ -406,12 +406,12 @@ impl DiagnosticPopover {
bottom: HOVER_POPOVER_GAP,
..Default::default()
})
.on_move(|_, _| {}) // Consume move events so they don't reach regions underneath.
.on_click(MouseButton::Left, |_, cx| {
.on_move(|_, _, _| {}) // Consume move events so they don't reach regions underneath.
.on_click(MouseButton::Left, |_, _, cx| {
cx.dispatch_action(GoToDiagnostic)
})
.with_cursor_style(CursorStyle::PointingHand)
.with_tooltip::<PrimaryDiagnostic, _>(
.with_tooltip::<PrimaryDiagnostic>(
0,
"Go To Diagnostic".to_string(),
Some(Box::new(crate::GoToDiagnostic)),

View file

@ -8,7 +8,7 @@ use collections::HashSet;
use futures::future::try_join_all;
use gpui::{
elements::*, geometry::vector::vec2f, AppContext, Entity, ModelHandle, Subscription, Task,
View, ViewContext, ViewContext, ViewHandle, WeakViewHandle,
View, ViewContext, ViewHandle, WeakViewHandle,
};
use language::{
proto::serialize_anchor as serialize_text_anchor, Bias, Buffer, OffsetRangeExt, Point,
@ -526,7 +526,7 @@ impl Item for Editor {
detail: Option<usize>,
style: &theme::Tab,
cx: &AppContext,
) -> ElementBox {
) -> ElementBox<Pane> {
Flex::row()
.with_child(
Label::new(self.title(cx).to_string(), style.label.clone())
@ -606,7 +606,7 @@ impl Item for Editor {
self.report_event("save editor", cx);
let format = self.perform_format(project.clone(), FormatTrigger::Save, cx);
let buffers = self.buffer().clone().read(cx).all_buffers();
cx.as_mut().spawn(|mut cx| async move {
cx.spawn(|_, mut cx| async move {
format.await?;
if buffers.len() == 1 {
@ -727,7 +727,7 @@ impl Item for Editor {
ToolbarItemLocation::PrimaryLeft { flex: None }
}
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox>> {
fn breadcrumbs(&self, theme: &theme::Theme, cx: &AppContext) -> Option<Vec<ElementBox<Pane>>> {
let cursor = self.selections.newest_anchor().head();
let multibuffer = &self.buffer().read(cx);
let (buffer_id, symbols) =
@ -1078,7 +1078,7 @@ impl View for CursorPosition {
"CursorPosition"
}
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> ElementBox<Self> {
if let Some(position) = self.position {
let theme = &cx.global::<Settings>().theme.workspace.status_bar;
let mut text = format!("{},{}", position.row + 1, position.column + 1);