Use a block decoration for entering rename text

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Max Brunsfeld 2022-02-18 13:15:22 -08:00
parent d705244210
commit f0a6e8cb9c
7 changed files with 113 additions and 63 deletions

View File

@ -480,7 +480,9 @@ struct SnippetState {
struct RenameState {
range: Range<Anchor>,
first_transaction: Option<TransactionId>,
old_name: String,
editor: ViewHandle<Editor>,
block_id: BlockId,
}
struct InvalidationStack<T>(Vec<T>);
@ -3161,6 +3163,26 @@ impl Editor {
}
pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
if let Some((range, column, _, _)) = self.take_rename(cx) {
let snapshot = self.buffer.read(cx).snapshot(cx);
let position = snapshot.clip_point(
range.start.to_point(&snapshot) + Point::new(0, column),
Bias::Left,
);
self.update_selections(
vec![Selection {
id: self.newest_anchor_selection().id,
start: position,
end: position,
reversed: false,
goal: SelectionGoal::None,
}],
None,
cx,
);
return;
}
if let Some(context_menu) = self.context_menu.as_mut() {
if context_menu.select_prev(cx) {
return;
@ -4118,20 +4140,51 @@ impl Editor {
let start = offset - lookbehind;
let end = offset + lookahead;
let rename_range = buffer.anchor_before(start)..buffer.anchor_after(end);
let old_name = buffer.text_for_range(start..end).collect::<String>();
drop(buffer);
this.buffer
.update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
this.pending_rename = Some(RenameState {
range: rename_range.clone(),
first_transaction: None,
let editor = cx.add_view(|cx| {
let mut editor = Editor::single_line(this.build_settings.clone(), cx);
editor
.buffer
.update(cx, |buffer, cx| buffer.edit([0..0], &old_name, cx));
editor.select_ranges([0..old_name.len()], None, cx);
editor.highlight_ranges::<Rename>(
vec![Anchor::min()..Anchor::max()],
settings.style.diff_background_inserted,
cx,
);
editor
});
this.select_ranges([start..end], None, cx);
this.highlight_ranges::<Rename>(
vec![rename_range],
settings.style.highlighted_line_background,
vec![rename_range.clone()],
settings.style.diff_background_deleted,
cx,
);
cx.focus(&editor);
let block_id = this.insert_blocks(
[BlockProperties {
position: rename_range.start.clone(),
height: 1,
render: Arc::new({
let editor = editor.clone();
move |cx: &BlockContext| {
ChildView::new(editor.clone())
.contained()
.with_padding_left(cx.anchor_x)
.boxed()
}
}),
disposition: BlockDisposition::Below,
}],
cx,
)[0];
this.pending_rename = Some(RenameState {
range: rename_range,
old_name,
editor,
block_id,
});
});
}
@ -4146,13 +4199,13 @@ impl Editor {
) -> Option<Task<Result<()>>> {
let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
let (buffer, range, new_name) = editor.update(cx, |editor, cx| {
let (range, new_name) = editor.take_rename(cx)?;
let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
let (range, _, old_name, new_name) = editor.take_rename(cx)?;
let buffer = editor.buffer.read(cx);
let (start_buffer, start) = buffer.text_anchor_for_position(range.start.clone(), cx)?;
let (end_buffer, end) = buffer.text_anchor_for_position(range.end.clone(), cx)?;
if start_buffer == end_buffer {
Some((start_buffer, start..end, new_name))
Some((start_buffer, start..end, old_name, new_name))
} else {
None
}
@ -4168,55 +4221,36 @@ impl Editor {
)
});
let transaction = buffer.update(cx, |buffer, cx| {
buffer.finalize_last_transaction();
buffer.start_transaction();
buffer.edit([range], &new_name, cx);
if buffer.end_transaction(cx).is_some() {
let transaction = buffer.finalize_last_transaction().unwrap().clone();
buffer.forget_transaction(transaction.id);
Some(transaction)
} else {
None
}
});
Some(cx.spawn(|workspace, mut cx| async move {
Some(cx.spawn(|workspace, cx| async move {
let project_transaction = rename.await?;
if let Some(transaction) = transaction {
buffer.update(&mut cx, |buffer, cx| {
buffer.push_transaction(transaction, Instant::now());
buffer.undo(cx);
});
}
Self::open_project_transaction(
editor,
workspace,
project_transaction,
format!("Rename: {}", new_name),
format!("Rename: {}{}", old_name, new_name),
cx,
)
.await
}))
}
fn take_rename(&mut self, cx: &mut ViewContext<Self>) -> Option<(Range<Anchor>, String)> {
fn take_rename(
&mut self,
cx: &mut ViewContext<Self>,
) -> Option<(Range<Anchor>, u32, String, String)> {
let rename = self.pending_rename.take()?;
let new_name = self
.buffer
.read(cx)
.read(cx)
.text_for_range(rename.range.clone())
.collect::<String>();
let editor = rename.editor.read(cx);
let new_name = editor.text(cx);
let buffer = editor.buffer.read(cx).snapshot(cx);
let rename_position = editor.newest_selection::<Point>(&buffer);
self.remove_blocks([rename.block_id].into_iter().collect(), cx);
self.clear_highlighted_ranges::<Rename>(cx);
if let Some(transaction_id) = rename.first_transaction {
self.buffer.update(cx, |buffer, cx| {
buffer.undo_to_transaction(transaction_id, false, cx)
});
}
Some((rename.range, new_name))
Some((
rename.range,
rename_position.head().column,
rename.old_name,
new_name,
))
}
fn invalidate_rename_range(
@ -4722,12 +4756,6 @@ impl Editor {
.buffer
.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
{
if let Some(rename) = self.pending_rename.as_mut() {
if rename.first_transaction.is_none() {
rename.first_transaction = Some(tx_id);
}
}
if let Some((_, end_selections)) = self.selection_history.get_mut(&tx_id) {
*end_selections = Some(self.selections.clone());
} else {
@ -5146,6 +5174,8 @@ impl EditorSettings {
gutter_padding_factor: 2.,
active_line_background: Default::default(),
highlighted_line_background: Default::default(),
diff_background_deleted: Default::default(),
diff_background_inserted: Default::default(),
line_number: Default::default(),
line_number_active: Default::default(),
selection: Default::default(),

View File

@ -299,7 +299,7 @@ impl EditorElement {
if let Some((row, indicator)) = layout.code_actions_indicator.as_mut() {
let mut x = bounds.width() - layout.gutter_padding;
let mut y = *row as f32 * layout.line_height - scroll_top;
x += ((layout.gutter_padding + layout.text_offset.x()) - indicator.size().x()) / 2.;
x += ((layout.gutter_padding + layout.gutter_margin) - indicator.size().x()) / 2.;
y += (layout.line_height - indicator.size().y()) / 2.;
indicator.paint(bounds.origin() + vec2f(x, y), visible_bounds, cx);
}
@ -321,7 +321,7 @@ impl EditorElement {
let end_row = ((scroll_top + bounds.height()) / layout.line_height).ceil() as u32 + 1; // Add 1 to ensure selections bleed off screen
let max_glyph_width = layout.em_width;
let scroll_left = scroll_position.x() * max_glyph_width;
let content_origin = bounds.origin() + layout.text_offset;
let content_origin = bounds.origin() + layout.gutter_margin;
cx.scene.push_layer(Some(bounds));
@ -776,22 +776,24 @@ impl Element for EditorElement {
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_width = self.max_line_number_width(&snapshot, cx) + gutter_padding * 2.0;
gutter_margin = -style.text.descent(cx.font_cache);
} else {
gutter_padding = 0.0;
gutter_width = 0.0
gutter_width = 0.0;
gutter_margin = 0.0;
};
let text_width = size.x() - gutter_width;
let text_offset = vec2f(-style.text.descent(cx.font_cache), 0.);
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 wrap_width = match self.settings.soft_wrap {
SoftWrap::None => None,
SoftWrap::EditorWidth => Some(text_width - text_offset.x() - overscroll.x() - em_width),
SoftWrap::EditorWidth => Some(text_width - gutter_margin - overscroll.x() - em_width),
SoftWrap::Column(column) => Some(column as f32 * em_advance),
};
let snapshot = self.update_view(cx.app, |view, cx| {
@ -991,7 +993,7 @@ impl Element for EditorElement {
gutter_padding,
gutter_width,
em_width,
gutter_width + text_offset.x(),
gutter_width + gutter_margin,
line_height,
&style,
&line_layouts,
@ -1006,7 +1008,7 @@ impl Element for EditorElement {
gutter_size,
gutter_padding,
text_size,
text_offset,
gutter_margin,
snapshot,
active_rows,
highlighted_rows,
@ -1080,6 +1082,12 @@ impl Element for EditorElement {
}
}
for (_, block) in &mut layout.blocks {
if block.dispatch_event(event, cx) {
return true;
}
}
match event {
Event::LeftMouseDown {
position,
@ -1123,6 +1131,7 @@ pub struct LayoutState {
scroll_max: Vector2F,
gutter_size: Vector2F,
gutter_padding: f32,
gutter_margin: f32,
text_size: Vector2F,
snapshot: EditorSnapshot,
active_rows: BTreeMap<u32, bool>,
@ -1135,7 +1144,6 @@ pub struct LayoutState {
em_advance: f32,
highlighted_ranges: Vec<(Range<DisplayPoint>, Color)>,
selections: HashMap<ReplicaId, Vec<text::Selection<DisplayPoint>>>,
text_offset: Vector2F,
context_menu: Option<(DisplayPoint, ElementBox)>,
code_actions_indicator: Option<(u32, ElementBox)>,
}

View File

@ -278,6 +278,8 @@ pub struct EditorStyle {
pub gutter_padding_factor: f32,
pub active_line_background: Color,
pub highlighted_line_background: Color,
pub diff_background_deleted: Color,
pub diff_background_inserted: Color,
pub line_number: Color,
pub line_number_active: Color,
pub guest_selections: Vec<SelectionStyle>,
@ -383,6 +385,8 @@ impl InputEditorStyle {
gutter_padding_factor: Default::default(),
active_line_background: Default::default(),
highlighted_line_background: Default::default(),
diff_background_deleted: Default::default(),
diff_background_inserted: Default::default(),
line_number: Default::default(),
line_number_active: Default::default(),
guest_selections: Default::default(),

View File

@ -188,7 +188,7 @@ corner_radius = 6
[project_panel]
extends = "$panel"
padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
padding.top = 6 # ($workspace.tab.height - $project_panel.entry.height) / 2
[project_panel.entry]
text = "$text.1"
@ -248,6 +248,8 @@ gutter_background = "$surface.1"
gutter_padding_factor = 2.5
active_line_background = "$state.active_line"
highlighted_line_background = "$state.highlighted_line"
diff_background_deleted = "$state.deleted_line"
diff_background_inserted = "$state.inserted_line"
line_number = "$text.2.color"
line_number_active = "$text.0.color"
selection = "$selection.host"

View File

@ -39,6 +39,8 @@ bad = "#b7372e"
[state]
active_line = "#161313"
highlighted_line = "#faca5033"
deleted_line = "#dd000022"
inserted_line = "#00dd0022"
hover = "#00000033"
selected = "#00000088"

View File

@ -39,6 +39,8 @@ bad = "#b7372e"
[state]
active_line = "#00000022"
highlighted_line = "#faca5033"
deleted_line = "#dd000044"
inserted_line = "#00dd0044"
hover = "#00000033"
selected = "#00000088"

View File

@ -39,6 +39,8 @@ bad = "#b7372e"
[state]
active_line = "#00000008"
highlighted_line = "#faca5033"
deleted_line = "#dd000044"
inserted_line = "#00dd0044"
hover = "#0000000D"
selected = "#0000001c"