mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-28 19:02:35 +03:00
Implement shift-click to extend the newest selection
This commit is contained in:
parent
63089badf1
commit
d969f38850
@ -1,3 +1,5 @@
|
||||
use crate::BeginSelectionMode;
|
||||
|
||||
use super::{
|
||||
DisplayPoint, DisplayRow, Editor, EditorMode, EditorSettings, EditorStyle, Input, Scroll,
|
||||
Select, SelectPhase, Snapshot, MAX_LINE_LEN,
|
||||
@ -55,18 +57,27 @@ impl EditorElement {
|
||||
fn mouse_down(
|
||||
&self,
|
||||
position: Vector2F,
|
||||
shift: bool,
|
||||
cmd: bool,
|
||||
click_count: usize,
|
||||
layout: &mut LayoutState,
|
||||
paint: &mut PaintState,
|
||||
cx: &mut EventContext,
|
||||
) -> bool {
|
||||
let mode = if cmd {
|
||||
BeginSelectionMode::Add
|
||||
} else if shift {
|
||||
BeginSelectionMode::Extend
|
||||
} else {
|
||||
BeginSelectionMode::Update
|
||||
};
|
||||
|
||||
if paint.text_bounds.contains_point(position) {
|
||||
let snapshot = self.snapshot(cx.app);
|
||||
let position = paint.point_for_position(&snapshot, layout, position);
|
||||
cx.dispatch_action(Select(SelectPhase::Begin {
|
||||
position,
|
||||
add: cmd,
|
||||
mode,
|
||||
click_count,
|
||||
}));
|
||||
true
|
||||
@ -75,7 +86,7 @@ impl EditorElement {
|
||||
let position = paint.point_for_position(&snapshot, layout, position);
|
||||
cx.dispatch_action(Select(SelectPhase::Begin {
|
||||
position,
|
||||
add: cmd,
|
||||
mode,
|
||||
click_count: 3,
|
||||
}));
|
||||
true
|
||||
@ -858,9 +869,10 @@ impl Element for EditorElement {
|
||||
match event {
|
||||
Event::LeftMouseDown {
|
||||
position,
|
||||
shift,
|
||||
cmd,
|
||||
click_count,
|
||||
} => self.mouse_down(*position, *cmd, *click_count, layout, paint, cx),
|
||||
} => self.mouse_down(*position, *shift, *cmd, *click_count, layout, paint, cx),
|
||||
Event::LeftMouseUp { position } => self.mouse_up(*position, cx),
|
||||
Event::LeftMouseDragged { position } => {
|
||||
self.mouse_dragged(*position, layout, paint, cx)
|
||||
|
@ -273,7 +273,7 @@ struct SpannedRows {
|
||||
pub enum SelectPhase {
|
||||
Begin {
|
||||
position: DisplayPoint,
|
||||
add: bool,
|
||||
mode: BeginSelectionMode,
|
||||
click_count: usize,
|
||||
},
|
||||
Update {
|
||||
@ -283,8 +283,15 @@ pub enum SelectPhase {
|
||||
End,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum BeginSelectionMode {
|
||||
Update,
|
||||
Extend,
|
||||
Add,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum SelectMode {
|
||||
enum ExtendSelectionMode {
|
||||
Character,
|
||||
Word(Range<Anchor>),
|
||||
Line(Range<Anchor>),
|
||||
@ -338,7 +345,7 @@ pub struct Snapshot {
|
||||
|
||||
struct PendingSelection {
|
||||
selection: Selection<Anchor>,
|
||||
mode: SelectMode,
|
||||
mode: ExtendSelectionMode,
|
||||
}
|
||||
|
||||
struct AddSelectionsState {
|
||||
@ -643,9 +650,9 @@ impl Editor {
|
||||
match phase {
|
||||
SelectPhase::Begin {
|
||||
position,
|
||||
add,
|
||||
mode,
|
||||
click_count,
|
||||
} => self.begin_selection(*position, *add, *click_count, cx),
|
||||
} => self.begin_selection(*position, *mode, *click_count, cx),
|
||||
SelectPhase::Update {
|
||||
position,
|
||||
scroll_position,
|
||||
@ -657,7 +664,7 @@ impl Editor {
|
||||
fn begin_selection(
|
||||
&mut self,
|
||||
position: DisplayPoint,
|
||||
add: bool,
|
||||
begin_mode: BeginSelectionMode,
|
||||
click_count: usize,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
@ -670,18 +677,18 @@ impl Editor {
|
||||
let buffer = self.buffer.read(cx);
|
||||
let start;
|
||||
let end;
|
||||
let mode;
|
||||
let mut extend_mode;
|
||||
match click_count {
|
||||
1 => {
|
||||
start = buffer.anchor_before(position.to_point(&display_map));
|
||||
end = start.clone();
|
||||
mode = SelectMode::Character;
|
||||
extend_mode = ExtendSelectionMode::Character;
|
||||
}
|
||||
2 => {
|
||||
let range = movement::surrounding_word(&display_map, position);
|
||||
start = buffer.anchor_before(range.start.to_point(&display_map));
|
||||
end = buffer.anchor_before(range.end.to_point(&display_map));
|
||||
mode = SelectMode::Word(start.clone()..end.clone());
|
||||
extend_mode = ExtendSelectionMode::Word(start.clone()..end.clone());
|
||||
}
|
||||
3 => {
|
||||
let position = display_map.clip_point(position, Bias::Left);
|
||||
@ -693,15 +700,16 @@ impl Editor {
|
||||
|
||||
start = buffer.anchor_before(line_start.to_point(&display_map));
|
||||
end = buffer.anchor_before(next_line_start.to_point(&display_map));
|
||||
mode = SelectMode::Line(start.clone()..end.clone());
|
||||
extend_mode = ExtendSelectionMode::Line(start.clone()..end.clone());
|
||||
}
|
||||
_ => {
|
||||
start = buffer.anchor_before(0);
|
||||
end = buffer.anchor_before(buffer.len());
|
||||
mode = SelectMode::All;
|
||||
extend_mode = ExtendSelectionMode::All;
|
||||
}
|
||||
}
|
||||
let selection = Selection {
|
||||
|
||||
let mut selection = Selection {
|
||||
id: post_inc(&mut self.next_selection_id),
|
||||
start,
|
||||
end,
|
||||
@ -709,10 +717,35 @@ impl Editor {
|
||||
goal: SelectionGoal::None,
|
||||
};
|
||||
|
||||
if !add {
|
||||
self.update_selections::<usize>(Vec::new(), false, cx);
|
||||
match begin_mode {
|
||||
BeginSelectionMode::Update => {
|
||||
self.update_selections::<usize>(Vec::new(), false, cx);
|
||||
}
|
||||
BeginSelectionMode::Extend => {
|
||||
let position = position.to_offset(&display_map, Bias::Left);
|
||||
let tail = self.newest_selection::<usize>(cx).tail();
|
||||
let tail_anchor = buffer.anchor_before(tail);
|
||||
if position >= tail {
|
||||
selection.start = tail_anchor.clone();
|
||||
} else {
|
||||
selection.end = tail_anchor.clone();
|
||||
selection.reversed = true;
|
||||
}
|
||||
match &mut extend_mode {
|
||||
ExtendSelectionMode::Word(range) | ExtendSelectionMode::Line(range) => {
|
||||
*range = tail_anchor.clone()..tail_anchor
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.update_selections::<usize>(Vec::new(), false, cx);
|
||||
}
|
||||
BeginSelectionMode::Add => {}
|
||||
}
|
||||
self.pending_selection = Some(PendingSelection { selection, mode });
|
||||
|
||||
self.pending_selection = Some(PendingSelection {
|
||||
selection,
|
||||
mode: extend_mode,
|
||||
});
|
||||
|
||||
cx.notify();
|
||||
}
|
||||
@ -729,11 +762,11 @@ impl Editor {
|
||||
let head;
|
||||
let tail;
|
||||
match mode {
|
||||
SelectMode::Character => {
|
||||
ExtendSelectionMode::Character => {
|
||||
head = position.to_point(&display_map);
|
||||
tail = selection.tail().to_point(buffer);
|
||||
}
|
||||
SelectMode::Word(original_range) => {
|
||||
ExtendSelectionMode::Word(original_range) => {
|
||||
let original_display_range = original_range.start.to_display_point(&display_map)
|
||||
..original_range.end.to_display_point(&display_map);
|
||||
let original_buffer_range = original_display_range.start.to_point(&display_map)
|
||||
@ -757,7 +790,7 @@ impl Editor {
|
||||
tail = original_buffer_range.start;
|
||||
}
|
||||
}
|
||||
SelectMode::Line(original_range) => {
|
||||
ExtendSelectionMode::Line(original_range) => {
|
||||
let original_display_range = original_range.start.to_display_point(&display_map)
|
||||
..original_range.end.to_display_point(&display_map);
|
||||
let original_buffer_range = original_display_range.start.to_point(&display_map)
|
||||
@ -780,7 +813,7 @@ impl Editor {
|
||||
tail = original_buffer_range.start;
|
||||
}
|
||||
}
|
||||
SelectMode::All => {
|
||||
ExtendSelectionMode::All => {
|
||||
return;
|
||||
}
|
||||
};
|
||||
@ -3254,7 +3287,7 @@ mod tests {
|
||||
cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
|
||||
view.begin_selection(DisplayPoint::new(2, 2), BeginSelectionMode::Update, 1, cx);
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
@ -3291,7 +3324,7 @@ mod tests {
|
||||
);
|
||||
|
||||
editor.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 3), true, 1, cx);
|
||||
view.begin_selection(DisplayPoint::new(3, 3), BeginSelectionMode::Add, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(0, 0), Vector2F::zero(), cx);
|
||||
});
|
||||
|
||||
@ -3320,7 +3353,7 @@ mod tests {
|
||||
let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(2, 2), false, 1, cx);
|
||||
view.begin_selection(DisplayPoint::new(2, 2), BeginSelectionMode::Update, 1, cx);
|
||||
assert_eq!(
|
||||
view.selection_ranges(cx),
|
||||
[DisplayPoint::new(2, 2)..DisplayPoint::new(2, 2)]
|
||||
@ -3352,11 +3385,11 @@ mod tests {
|
||||
let (_, view) = cx.add_window(Default::default(), |cx| build_editor(buffer, settings, cx));
|
||||
|
||||
view.update(cx, |view, cx| {
|
||||
view.begin_selection(DisplayPoint::new(3, 4), false, 1, cx);
|
||||
view.begin_selection(DisplayPoint::new(3, 4), BeginSelectionMode::Update, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(1, 1), Vector2F::zero(), cx);
|
||||
view.end_selection(cx);
|
||||
|
||||
view.begin_selection(DisplayPoint::new(0, 1), true, 1, cx);
|
||||
view.begin_selection(DisplayPoint::new(0, 1), BeginSelectionMode::Add, 1, cx);
|
||||
view.update_selection(DisplayPoint::new(0, 3), Vector2F::zero(), cx);
|
||||
view.end_selection(cx);
|
||||
assert_eq!(
|
||||
|
@ -3650,6 +3650,7 @@ mod tests {
|
||||
presenter.borrow_mut().dispatch_event(
|
||||
Event::LeftMouseDown {
|
||||
position: Default::default(),
|
||||
shift: false,
|
||||
cmd: false,
|
||||
click_count: 1,
|
||||
},
|
||||
|
@ -15,6 +15,7 @@ pub enum Event {
|
||||
LeftMouseDown {
|
||||
position: Vector2F,
|
||||
cmd: bool,
|
||||
shift: bool,
|
||||
click_count: usize,
|
||||
},
|
||||
LeftMouseUp {
|
||||
|
@ -86,14 +86,14 @@ impl Event {
|
||||
})
|
||||
}
|
||||
NSEventType::NSLeftMouseDown => {
|
||||
let modifiers = native_event.modifierFlags();
|
||||
window_height.map(|window_height| Self::LeftMouseDown {
|
||||
position: vec2f(
|
||||
native_event.locationInWindow().x as f32,
|
||||
window_height - native_event.locationInWindow().y as f32,
|
||||
),
|
||||
cmd: native_event
|
||||
.modifierFlags()
|
||||
.contains(NSEventModifierFlags::NSCommandKeyMask),
|
||||
shift: modifiers.contains(NSEventModifierFlags::NSShiftKeyMask),
|
||||
cmd: modifiers.contains(NSEventModifierFlags::NSCommandKeyMask),
|
||||
click_count: native_event.clickCount() as usize,
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user