Merge branch 'main' into terminal-element
This commit is contained in:
@@ -24,7 +24,7 @@ use lsp::DiagnosticSeverity;
|
||||
use std::{any::TypeId, borrow::Cow, fmt::Debug, num::NonZeroU32, ops::Range, sync::Arc};
|
||||
use sum_tree::{Bias, TreeMap};
|
||||
use tab_map::TabMap;
|
||||
use theme::{SyntaxTheme, Theme};
|
||||
use theme::{StatusColors, SyntaxTheme, Theme};
|
||||
use wrap_map::WrapMap;
|
||||
|
||||
pub use block_map::{
|
||||
@@ -513,8 +513,8 @@ impl DisplaySnapshot {
|
||||
self.chunks(
|
||||
display_rows,
|
||||
language_aware,
|
||||
Some(editor_style.syntax.inlay_style),
|
||||
Some(editor_style.syntax.suggestion_style),
|
||||
Some(editor_style.inlays_style),
|
||||
Some(editor_style.suggestions_style),
|
||||
)
|
||||
.map(|chunk| {
|
||||
let mut highlight_style = chunk
|
||||
|
||||
@@ -993,7 +993,7 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::display_map::inlay_map::InlayMap;
|
||||
use crate::display_map::{fold_map::FoldMap, tab_map::TabMap, wrap_map::WrapMap};
|
||||
use gpui::{div, font, px, Element, Platform as _};
|
||||
use gpui::{div, font, px, Element};
|
||||
use multi_buffer::MultiBuffer;
|
||||
use rand::prelude::*;
|
||||
use settings::SettingsStore;
|
||||
@@ -1185,11 +1185,7 @@ mod tests {
|
||||
fn test_blocks_on_wrapped_lines(cx: &mut gpui::TestAppContext) {
|
||||
cx.update(|cx| init_test(cx));
|
||||
|
||||
let font_id = cx
|
||||
.test_platform
|
||||
.text_system()
|
||||
.font_id(&font("Helvetica"))
|
||||
.unwrap();
|
||||
let font_id = cx.text_system().font_id(&font("Helvetica")).unwrap();
|
||||
|
||||
let text = "one two three\nfour five six\nseven eight";
|
||||
|
||||
|
||||
@@ -1032,7 +1032,7 @@ mod tests {
|
||||
display_map::{fold_map::FoldMap, inlay_map::InlayMap, tab_map::TabMap},
|
||||
MultiBuffer,
|
||||
};
|
||||
use gpui::{font, px, test::observe, Platform};
|
||||
use gpui::{font, px, test::observe};
|
||||
use rand::prelude::*;
|
||||
use settings::SettingsStore;
|
||||
use smol::stream::StreamExt;
|
||||
|
||||
@@ -92,6 +92,7 @@ use std::{
|
||||
ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
|
||||
path::Path,
|
||||
sync::Arc,
|
||||
sync::Weak,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
pub use sum_tree::Bias;
|
||||
@@ -420,6 +421,25 @@ pub fn init(cx: &mut AppContext) {
|
||||
},
|
||||
)
|
||||
.detach();
|
||||
|
||||
cx.on_action(move |_: &workspace::NewFile, cx| {
|
||||
let app_state = cx.global::<Weak<workspace::AppState>>();
|
||||
if let Some(app_state) = app_state.upgrade() {
|
||||
workspace::open_new(&app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
cx.on_action(move |_: &workspace::NewWindow, cx| {
|
||||
let app_state = cx.global::<Weak<workspace::AppState>>();
|
||||
if let Some(app_state) = app_state.upgrade() {
|
||||
workspace::open_new(&app_state, cx, |workspace, cx| {
|
||||
Editor::new_file(workspace, &Default::default(), cx)
|
||||
})
|
||||
.detach();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
trait InvalidationRegion {
|
||||
@@ -479,6 +499,8 @@ pub struct EditorStyle {
|
||||
pub scrollbar_width: Pixels,
|
||||
pub syntax: Arc<SyntaxTheme>,
|
||||
pub diagnostic_style: DiagnosticStyle,
|
||||
pub inlays_style: HighlightStyle,
|
||||
pub suggestions_style: HighlightStyle,
|
||||
}
|
||||
|
||||
type CompletionId = usize;
|
||||
@@ -1675,8 +1697,7 @@ impl Editor {
|
||||
if let Some(project) = project.as_ref() {
|
||||
if buffer.read(cx).is_singleton() {
|
||||
project_subscriptions.push(cx.observe(project, |_, _, cx| {
|
||||
cx.emit(ItemEvent::UpdateTab);
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
cx.emit(EditorEvent::TitleChanged);
|
||||
}));
|
||||
}
|
||||
project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
|
||||
@@ -1961,14 +1982,14 @@ impl Editor {
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
|
||||
// self.cursor_shape = cursor_shape;
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
|
||||
self.cursor_shape = cursor_shape;
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
|
||||
// self.collapse_matches = collapse_matches;
|
||||
// }
|
||||
pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
|
||||
self.collapse_matches = collapse_matches;
|
||||
}
|
||||
|
||||
pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
|
||||
if self.collapse_matches {
|
||||
@@ -1977,56 +1998,47 @@ impl Editor {
|
||||
range.clone()
|
||||
}
|
||||
|
||||
// pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
|
||||
// if self.display_map.read(cx).clip_at_line_ends != clip {
|
||||
// self.display_map
|
||||
// .update(cx, |map, _| map.clip_at_line_ends = clip);
|
||||
// }
|
||||
// }
|
||||
pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
|
||||
if self.display_map.read(cx).clip_at_line_ends != clip {
|
||||
self.display_map
|
||||
.update(cx, |map, _| map.clip_at_line_ends = clip);
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn set_keymap_context_layer<Tag: 'static>(
|
||||
// &mut self,
|
||||
// context: KeymapContext,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) {
|
||||
// self.keymap_context_layers
|
||||
// .insert(TypeId::of::<Tag>(), context);
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_keymap_context_layer<Tag: 'static>(
|
||||
&mut self,
|
||||
context: KeyContext,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
self.keymap_context_layers
|
||||
.insert(TypeId::of::<Tag>(), context);
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
|
||||
// self.keymap_context_layers.remove(&TypeId::of::<Tag>());
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
|
||||
self.keymap_context_layers.remove(&TypeId::of::<Tag>());
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
// pub fn set_input_enabled(&mut self, input_enabled: bool) {
|
||||
// self.input_enabled = input_enabled;
|
||||
// }
|
||||
pub fn set_input_enabled(&mut self, input_enabled: bool) {
|
||||
self.input_enabled = input_enabled;
|
||||
}
|
||||
|
||||
// pub fn set_autoindent(&mut self, autoindent: bool) {
|
||||
// if autoindent {
|
||||
// self.autoindent_mode = Some(AutoindentMode::EachLine);
|
||||
// } else {
|
||||
// self.autoindent_mode = None;
|
||||
// }
|
||||
// }
|
||||
pub fn set_autoindent(&mut self, autoindent: bool) {
|
||||
if autoindent {
|
||||
self.autoindent_mode = Some(AutoindentMode::EachLine);
|
||||
} else {
|
||||
self.autoindent_mode = None;
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn read_only(&self) -> bool {
|
||||
// self.read_only
|
||||
// }
|
||||
pub fn read_only(&self) -> bool {
|
||||
self.read_only
|
||||
}
|
||||
|
||||
// pub fn set_read_only(&mut self, read_only: bool) {
|
||||
// self.read_only = read_only;
|
||||
// }
|
||||
|
||||
// pub fn set_field_editor_style(
|
||||
// &mut self,
|
||||
// style: Option<Arc<GetFieldEditorTheme>>,
|
||||
// cx: &mut ViewContext<Self>,
|
||||
// ) {
|
||||
// self.get_field_editor_theme = style;
|
||||
// cx.notify();
|
||||
// }
|
||||
pub fn set_read_only(&mut self, read_only: bool) {
|
||||
self.read_only = read_only;
|
||||
}
|
||||
|
||||
fn selections_did_change(
|
||||
&mut self,
|
||||
@@ -2141,10 +2153,6 @@ impl Editor {
|
||||
cx.emit(SearchEvent::ActiveMatchChanged)
|
||||
}
|
||||
|
||||
if local {
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
|
||||
@@ -7634,6 +7642,18 @@ impl Editor {
|
||||
.editor_style
|
||||
.diagnostic_style
|
||||
.clone(),
|
||||
// todo!("what about the rest of the highlight style parts for inlays and suggestions?")
|
||||
inlays_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().hint),
|
||||
font_weight: Some(FontWeight::BOLD),
|
||||
fade_out: Some(0.6),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
suggestions_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
fade_out: Some(0.6),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
},
|
||||
))
|
||||
.into_any_element()
|
||||
@@ -8573,8 +8593,6 @@ impl Editor {
|
||||
self.update_visible_copilot_suggestion(cx);
|
||||
}
|
||||
cx.emit(EditorEvent::BufferEdited);
|
||||
cx.emit(ItemEvent::Edit);
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
cx.emit(SearchEvent::MatchesInvalidated);
|
||||
|
||||
if *sigleton_buffer_edited {
|
||||
@@ -8622,20 +8640,14 @@ impl Editor {
|
||||
self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
|
||||
cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
|
||||
}
|
||||
multi_buffer::Event::Reparsed => {
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
multi_buffer::Event::DirtyChanged => {
|
||||
cx.emit(ItemEvent::UpdateTab);
|
||||
}
|
||||
multi_buffer::Event::Saved
|
||||
| multi_buffer::Event::FileHandleChanged
|
||||
| multi_buffer::Event::Reloaded => {
|
||||
cx.emit(ItemEvent::UpdateTab);
|
||||
cx.emit(ItemEvent::UpdateBreadcrumbs);
|
||||
multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
|
||||
multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
|
||||
multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
|
||||
multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
|
||||
cx.emit(EditorEvent::TitleChanged)
|
||||
}
|
||||
multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
|
||||
multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
|
||||
multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
|
||||
multi_buffer::Event::DiagnosticsUpdated => {
|
||||
self.refresh_active_diagnostics(cx);
|
||||
}
|
||||
@@ -9279,7 +9291,7 @@ impl Render for Editor {
|
||||
color: cx.theme().colors().text,
|
||||
font_family: settings.buffer_font.family.clone(),
|
||||
font_features: settings.buffer_font.features,
|
||||
font_size: settings.buffer_font_size.into(),
|
||||
font_size: settings.buffer_font_size(cx).into(),
|
||||
font_weight: FontWeight::NORMAL,
|
||||
font_style: FontStyle::Normal,
|
||||
line_height: relative(settings.buffer_line_height.value()),
|
||||
@@ -9304,6 +9316,19 @@ impl Render for Editor {
|
||||
scrollbar_width: px(12.),
|
||||
syntax: cx.theme().syntax().clone(),
|
||||
diagnostic_style: cx.theme().diagnostic_style(),
|
||||
// TODO kb find `HighlightStyle` usages
|
||||
// todo!("what about the rest of the highlight style parts?")
|
||||
inlays_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().hint),
|
||||
font_weight: Some(FontWeight::BOLD),
|
||||
fade_out: Some(0.6),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
suggestions_style: HighlightStyle {
|
||||
color: Some(cx.theme().status().predictive),
|
||||
fade_out: Some(0.6),
|
||||
..HighlightStyle::default()
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ use futures::StreamExt;
|
||||
use gpui::{
|
||||
div,
|
||||
serde_json::{self, json},
|
||||
Div, Flatten, Platform, TestAppContext, VisualTestContext, WindowBounds, WindowOptions,
|
||||
Div, Flatten, TestAppContext, VisualTestContext, WindowBounds, WindowOptions,
|
||||
};
|
||||
use indoc::indoc;
|
||||
use language::{
|
||||
@@ -32,7 +32,7 @@ use util::{
|
||||
test::{marked_text_ranges, marked_text_ranges_by, sample_text, TextRangeMarker},
|
||||
};
|
||||
use workspace::{
|
||||
item::{FollowEvent, FollowableEvents, FollowableItem, Item, ItemHandle},
|
||||
item::{FollowEvent, FollowableItem, Item, ItemHandle},
|
||||
NavigationEntry, ViewId,
|
||||
};
|
||||
|
||||
@@ -345,7 +345,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
|
||||
);
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(3, 3),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -356,7 +361,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
|
||||
);
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(1, 1),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -368,7 +378,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.end_selection(cx);
|
||||
view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(3, 3),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -380,7 +395,12 @@ fn test_selection_with_mouse(cx: &mut TestAppContext) {
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(0, 0), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(0, 0),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@@ -423,7 +443,12 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
|
||||
});
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.update_selection(DisplayPoint::new(3, 3), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(3, 3),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
assert_eq!(
|
||||
view.selections.display_ranges(cx),
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
|
||||
@@ -432,7 +457,12 @@ fn test_canceling_pending_selection(cx: &mut TestAppContext) {
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.cancel(&Cancel, cx);
|
||||
view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(1, 1),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
assert_eq!(
|
||||
view.selections.display_ranges(cx),
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(3, 3)]
|
||||
@@ -643,11 +673,21 @@ fn test_cancel(cx: &mut TestAppContext) {
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(1, 1), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(1, 1),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
view.end_selection(cx);
|
||||
|
||||
view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(0, 3), 0, gpui::Point::<f32>::zero(), cx);
|
||||
view.update_selection(
|
||||
DisplayPoint::new(0, 3),
|
||||
0,
|
||||
gpui::Point::<f32>::default(),
|
||||
cx,
|
||||
);
|
||||
view.end_selection(cx);
|
||||
assert_eq!(
|
||||
view.selections.display_ranges(cx),
|
||||
@@ -3238,9 +3278,7 @@ async fn test_clipboard(cx: &mut gpui::TestAppContext) {
|
||||
the lazy dog"});
|
||||
cx.update_editor(|e, cx| e.copy(&Copy, cx));
|
||||
assert_eq!(
|
||||
cx.test_platform
|
||||
.read_from_clipboard()
|
||||
.map(|item| item.text().to_owned()),
|
||||
cx.read_from_clipboard().map(|item| item.text().to_owned()),
|
||||
Some("fox jumps over\n".to_owned())
|
||||
);
|
||||
|
||||
@@ -6478,7 +6516,7 @@ async fn test_following(cx: &mut gpui::TestAppContext) {
|
||||
cx.subscribe(
|
||||
&follower.root_view(cx).unwrap(),
|
||||
move |_, _, event: &EditorEvent, cx| {
|
||||
if matches!(event.to_follow_event(), Some(FollowEvent::Unfollow)) {
|
||||
if matches!(Editor::to_follow_event(event), Some(FollowEvent::Unfollow)) {
|
||||
*is_still_following.borrow_mut() = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -485,7 +485,7 @@ impl EditorElement {
|
||||
let modifiers = event.modifiers;
|
||||
if editor.has_pending_selection() && event.pressed_button == Some(MouseButton::Left) {
|
||||
let point_for_position = position_map.point_for_position(text_bounds, event.position);
|
||||
let mut scroll_delta = gpui::Point::<f32>::zero();
|
||||
let mut scroll_delta = gpui::Point::<f32>::default();
|
||||
let vertical_margin = position_map.line_height.min(text_bounds.size.height / 3.0);
|
||||
let top = text_bounds.origin.y + vertical_margin;
|
||||
let bottom = text_bounds.lower_left().y - vertical_margin;
|
||||
@@ -511,7 +511,7 @@ impl EditorElement {
|
||||
position: point_for_position.previous_valid,
|
||||
goal_column: point_for_position.exact_unclipped.column(),
|
||||
scroll_position: (position_map.snapshot.scroll_position() + scroll_delta)
|
||||
.clamp(&gpui::Point::zero(), &position_map.scroll_max),
|
||||
.clamp(&gpui::Point::default(), &position_map.scroll_max),
|
||||
},
|
||||
cx,
|
||||
);
|
||||
@@ -2803,35 +2803,48 @@ impl Element for EditorElement {
|
||||
|
||||
let focus_handle = editor.focus_handle(cx);
|
||||
let dispatch_context = self.editor.read(cx).dispatch_context(cx);
|
||||
cx.with_key_dispatch(dispatch_context, Some(focus_handle.clone()), |_, cx| {
|
||||
self.register_actions(cx);
|
||||
self.register_key_listeners(cx);
|
||||
cx.with_key_dispatch(
|
||||
Some(dispatch_context),
|
||||
Some(focus_handle.clone()),
|
||||
|_, cx| {
|
||||
self.register_actions(cx);
|
||||
self.register_key_listeners(cx);
|
||||
|
||||
// We call with_z_index to establish a new stacking context.
|
||||
cx.with_z_index(0, |cx| {
|
||||
cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
|
||||
// Paint mouse listeners at z-index 0 so any elements we paint on top of the editor
|
||||
// take precedence.
|
||||
cx.with_z_index(0, |cx| {
|
||||
self.paint_mouse_listeners(bounds, gutter_bounds, text_bounds, &layout, cx);
|
||||
// We call with_z_index to establish a new stacking context.
|
||||
cx.with_z_index(0, |cx| {
|
||||
cx.with_content_mask(Some(ContentMask { bounds }), |cx| {
|
||||
// Paint mouse listeners at z-index 0 so any elements we paint on top of the editor
|
||||
// take precedence.
|
||||
cx.with_z_index(0, |cx| {
|
||||
self.paint_mouse_listeners(
|
||||
bounds,
|
||||
gutter_bounds,
|
||||
text_bounds,
|
||||
&layout,
|
||||
cx,
|
||||
);
|
||||
});
|
||||
let input_handler =
|
||||
ElementInputHandler::new(bounds, self.editor.clone(), cx);
|
||||
cx.handle_input(&focus_handle, input_handler);
|
||||
|
||||
self.paint_background(gutter_bounds, text_bounds, &layout, cx);
|
||||
if layout.gutter_size.width > Pixels::ZERO {
|
||||
self.paint_gutter(gutter_bounds, &mut layout, cx);
|
||||
}
|
||||
self.paint_text(text_bounds, &mut layout, cx);
|
||||
|
||||
if !layout.blocks.is_empty() {
|
||||
cx.with_z_index(1, |cx| {
|
||||
cx.with_element_id(Some("editor_blocks"), |cx| {
|
||||
self.paint_blocks(bounds, &mut layout, cx);
|
||||
})
|
||||
})
|
||||
}
|
||||
});
|
||||
let input_handler = ElementInputHandler::new(bounds, self.editor.clone(), cx);
|
||||
cx.handle_input(&focus_handle, input_handler);
|
||||
|
||||
self.paint_background(gutter_bounds, text_bounds, &layout, cx);
|
||||
if layout.gutter_size.width > Pixels::ZERO {
|
||||
self.paint_gutter(gutter_bounds, &mut layout, cx);
|
||||
}
|
||||
self.paint_text(text_bounds, &mut layout, cx);
|
||||
|
||||
if !layout.blocks.is_empty() {
|
||||
cx.with_element_id(Some("editor_blocks"), |cx| {
|
||||
self.paint_blocks(bounds, &mut layout, cx);
|
||||
})
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+72
-44
@@ -32,10 +32,10 @@ use std::{
|
||||
};
|
||||
use text::Selection;
|
||||
use theme::{ActiveTheme, Theme};
|
||||
use ui::{Color, Label};
|
||||
use ui::{h_stack, prelude::*, Label};
|
||||
use util::{paths::PathExt, paths::FILE_ROW_COLUMN_DELIMITER, ResultExt, TryFutureExt};
|
||||
use workspace::{
|
||||
item::{BreadcrumbText, FollowEvent, FollowableEvents, FollowableItemHandle},
|
||||
item::{BreadcrumbText, FollowEvent, FollowableItemHandle},
|
||||
StatusItemView,
|
||||
};
|
||||
use workspace::{
|
||||
@@ -46,27 +46,7 @@ use workspace::{
|
||||
|
||||
pub const MAX_TAB_TITLE_LEN: usize = 24;
|
||||
|
||||
impl FollowableEvents for EditorEvent {
|
||||
fn to_follow_event(&self) -> Option<workspace::item::FollowEvent> {
|
||||
match self {
|
||||
EditorEvent::Edited => Some(FollowEvent::Unfollow),
|
||||
EditorEvent::SelectionsChanged { local }
|
||||
| EditorEvent::ScrollPositionChanged { local, .. } => {
|
||||
if *local {
|
||||
Some(FollowEvent::Unfollow)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<ItemEvent> for Editor {}
|
||||
|
||||
impl FollowableItem for Editor {
|
||||
type FollowableEvent = EditorEvent;
|
||||
fn remote_id(&self) -> Option<ViewId> {
|
||||
self.remote_id
|
||||
}
|
||||
@@ -241,9 +221,24 @@ impl FollowableItem for Editor {
|
||||
}))
|
||||
}
|
||||
|
||||
fn to_follow_event(event: &EditorEvent) -> Option<workspace::item::FollowEvent> {
|
||||
match event {
|
||||
EditorEvent::Edited => Some(FollowEvent::Unfollow),
|
||||
EditorEvent::SelectionsChanged { local }
|
||||
| EditorEvent::ScrollPositionChanged { local, .. } => {
|
||||
if *local {
|
||||
Some(FollowEvent::Unfollow)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_event_to_update_proto(
|
||||
&self,
|
||||
event: &Self::FollowableEvent,
|
||||
event: &EditorEvent,
|
||||
update: &mut Option<proto::update_view::Variant>,
|
||||
cx: &WindowContext,
|
||||
) -> bool {
|
||||
@@ -528,6 +523,8 @@ fn deserialize_anchor(buffer: &MultiBufferSnapshot, anchor: proto::EditorAnchor)
|
||||
}
|
||||
|
||||
impl Item for Editor {
|
||||
type Event = EditorEvent;
|
||||
|
||||
fn navigate(&mut self, data: Box<dyn std::any::Any>, cx: &mut ViewContext<Self>) -> bool {
|
||||
if let Ok(data) = data.downcast::<NavigationData>() {
|
||||
let newest_selection = self.selections.newest::<Point>(cx);
|
||||
@@ -586,28 +583,25 @@ impl Item for Editor {
|
||||
fn tab_content(&self, detail: Option<usize>, cx: &WindowContext) -> AnyElement {
|
||||
let theme = cx.theme();
|
||||
|
||||
AnyElement::new(
|
||||
div()
|
||||
.flex()
|
||||
.flex_row()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.child(Label::new(self.title(cx).to_string()))
|
||||
.children(detail.and_then(|detail| {
|
||||
let path = path_for_buffer(&self.buffer, detail, false, cx)?;
|
||||
let description = path.to_string_lossy();
|
||||
let description = detail.and_then(|detail| {
|
||||
let path = path_for_buffer(&self.buffer, detail, false, cx)?;
|
||||
let description = path.to_string_lossy();
|
||||
let description = description.trim();
|
||||
|
||||
Some(
|
||||
div().child(
|
||||
Label::new(util::truncate_and_trailoff(
|
||||
&description,
|
||||
MAX_TAB_TITLE_LEN,
|
||||
))
|
||||
.color(Color::Muted),
|
||||
),
|
||||
)
|
||||
})),
|
||||
)
|
||||
if description.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(util::truncate_and_trailoff(&description, MAX_TAB_TITLE_LEN))
|
||||
});
|
||||
|
||||
h_stack()
|
||||
.gap_2()
|
||||
.child(Label::new(self.title(cx).to_string()))
|
||||
.when_some(description, |this, description| {
|
||||
this.child(Label::new(description).color(Color::Muted))
|
||||
})
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn for_each_project_item(
|
||||
@@ -841,6 +835,40 @@ impl Item for Editor {
|
||||
Some("Editor")
|
||||
}
|
||||
|
||||
fn to_item_events(event: &EditorEvent, mut f: impl FnMut(ItemEvent)) {
|
||||
match event {
|
||||
EditorEvent::Closed => f(ItemEvent::CloseItem),
|
||||
|
||||
EditorEvent::Saved | EditorEvent::TitleChanged => {
|
||||
f(ItemEvent::UpdateTab);
|
||||
f(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
EditorEvent::Reparsed => {
|
||||
f(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
EditorEvent::SelectionsChanged { local } if *local => {
|
||||
f(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
EditorEvent::DirtyChanged => {
|
||||
f(ItemEvent::UpdateTab);
|
||||
}
|
||||
|
||||
EditorEvent::BufferEdited => {
|
||||
f(ItemEvent::Edit);
|
||||
f(ItemEvent::UpdateBreadcrumbs);
|
||||
}
|
||||
|
||||
EditorEvent::ExcerptsAdded { .. } | EditorEvent::ExcerptsRemoved { .. } => {
|
||||
f(ItemEvent::Edit);
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize(
|
||||
project: Model<Project>,
|
||||
_workspace: WeakView<Workspace>,
|
||||
|
||||
Reference in New Issue
Block a user