on master help sign in
mouse: Remove verify_screen_coords, refactor primary selection modification
62eb8c6Blaž Hrastnik
helix-core/src/selection.rs+7
@@ -329,11 +329,18 @@ pub struct Selection {
329impl Selection {
329impl Selection {
330 // eq
330 // eq
331
331
332+ #[inline]
332 #[must_use]
333 #[must_use]
333 pub fn primary(&self) -> Range {
334 pub fn primary(&self) -> Range {
334 self.ranges[self.primary_index]
335 self.ranges[self.primary_index]
335 }
336 }
336
337
338+ #[inline]
339+ #[must_use]
340+ pub fn primary_mut(&mut self) -> &mut Range {
341+ &mut self.ranges[self.primary_index]
342+ }
343+
337 /// Ensure selection containing only the primary selection.
344 /// Ensure selection containing only the primary selection.
338 pub fn into_single(self) -> Self {
345 pub fn into_single(self) -> Self {
339 if self.ranges.len() == 1 {
346 if self.ranges.len() == 1 {
helix-term/src/ui/editor.rs+16−27
@@ -815,25 +815,21 @@ impl Component for EditorView {
815 let editor = &mut cx.editor;
815 let editor = &mut cx.editor;
816
816
817 let result = editor.tree.views().find_map(|(view, _focus)| {
817 let result = editor.tree.views().find_map(|(view, _focus)| {
818− view.pos_at_screen_coords(
818+ view.pos_at_screen_coords(&editor.documents[view.doc], row, column)
819− &editor.documents[view.doc],
820− row as usize,
821− column as usize,
822− )
823− .map(|pos| (pos, view.id))
819+ .map(|pos| (pos, view.id))
824 });
820 });
825
821
826− if let Some((pos, id)) = result {
822+ if let Some((pos, view_id)) = result {
827− let doc = &mut editor.documents[editor.tree.get(id).doc];
823+ let doc = &mut editor.documents[editor.tree.get(view_id).doc];
828
824
829 if modifiers == crossterm::event::KeyModifiers::ALT {
825 if modifiers == crossterm::event::KeyModifiers::ALT {
830− let selection = doc.selection(id).clone();
826+ let selection = doc.selection(view_id).clone();
831− doc.set_selection(id, selection.push(Range::point(pos)));
827+ doc.set_selection(view_id, selection.push(Range::point(pos)));
832 } else {
828 } else {
833− doc.set_selection(id, Selection::point(pos));
829+ doc.set_selection(view_id, Selection::point(pos));
834 }
830 }
835
831
836− editor.tree.focus = id;
832+ editor.tree.focus = view_id;
837
833
838 return EventResult::Consumed(None);
834 return EventResult::Consumed(None);
839 }
835 }
@@ -849,22 +845,15 @@ impl Component for EditorView {
849 }) => {
845 }) => {
850 let (view, doc) = current!(cx.editor);
846 let (view, doc) = current!(cx.editor);
851
847
852− let pos = view.pos_at_screen_coords(doc, row as usize, column as usize);
848+ let pos = match view.pos_at_screen_coords(doc, row, column) {
853−
849+ Some(pos) => pos,
854− if pos == None {
855− return EventResult::Ignored;
850+ None => return EventResult::Ignored,
856− }
857−
858− let selection = doc.selection(view.id).clone();
859− let primary_anchor = selection.primary().anchor;
860− let new_selection = selection.transform(|range| -> Range {
861− if range.anchor == primary_anchor {
862− return Range::new(primary_anchor, pos.unwrap());
863− }
864− range
865− });
851+ };
866
852
853+ let mut selection = doc.selection(view.id).clone();
854+ let primary = selection.primary_mut();
855+ *primary = Range::new(primary.anchor, pos);
867− doc.set_selection(view.id, new_selection);
856+ doc.set_selection(view.id, selection);
868 EventResult::Consumed(None)
857 EventResult::Consumed(None)
869 }
858 }
870 Event::Mouse(_) => EventResult::Ignored,
859 Event::Mouse(_) => EventResult::Ignored,
helix-view/src/view.rs+14−29
@@ -166,38 +166,26 @@ impl View {
166 Some(Position::new(row, col))
166 Some(Position::new(row, col))
167 }
167 }
168
168
169− /// Verifies whether a screen position is inside the view
170− /// Returns true when position is inside the view
171− pub fn verify_screen_coords(&self, row: usize, column: usize) -> bool {
172− // 2 for status
173− if row < self.area.y as usize || row > self.area.y as usize + self.area.height as usize - 2
174− {
175− return false;
176− }
177−
178− // TODO: not ideal
179− const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
180−
181− if column < self.area.x as usize + OFFSET
182− || column > self.area.x as usize + self.area.width as usize
183− {
184− return false;
185− }
186− true
187− }
188−
189 pub fn text_pos_at_screen_coords(
169 pub fn text_pos_at_screen_coords(
190 &self,
170 &self,
191 text: &RopeSlice,
171 text: &RopeSlice,
192− row: usize,
172+ row: u16,
193− column: usize,
173+ column: u16,
194 tab_width: usize,
174 tab_width: usize,
195 ) -> Option<usize> {
175 ) -> Option<usize> {
196− if !self.verify_screen_coords(row, column) {
176+ // TODO: not ideal
177+ const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
178+
179+ // 2 for status
180+ if row < self.area.top() || row > self.area.bottom().saturating_sub(2) {
197 return None;
181 return None;
198 }
182 }
199
183
184+ if column < self.area.left() + OFFSET || column > self.area.right() {
185+ return None;
186+ }
187+
200− let line_number = row - self.area.y as usize + self.first_line;
188+ let line_number = (row - self.area.y) as usize + self.first_line;
201
189
202 if line_number > text.len_lines() - 1 {
190 if line_number > text.len_lines() - 1 {
203 return Some(text.len_chars());
191 return Some(text.len_chars());
@@ -207,10 +195,7 @@ impl View {
207
195
208 let current_line = text.line(line_number);
196 let current_line = text.line(line_number);
209
197
210− // TODO: not ideal
211− const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
212−
213− let target = column - OFFSET - self.area.x as usize + self.first_col;
198+ let target = (column - OFFSET - self.area.x) as usize + self.first_col;
214 let mut selected = 0;
199 let mut selected = 0;
215
200
216 for grapheme in RopeGraphemes::new(current_line) {
201 for grapheme in RopeGraphemes::new(current_line) {
@@ -231,7 +216,7 @@ impl View {
231
216
232 /// Translates a screen position to position in the text document.
217 /// Translates a screen position to position in the text document.
233 /// Returns a usize typed position in bounds of the text if found in this view, None if out of view.
218 /// Returns a usize typed position in bounds of the text if found in this view, None if out of view.
234− pub fn pos_at_screen_coords(&self, doc: &Document, row: usize, column: usize) -> Option<usize> {
219+ pub fn pos_at_screen_coords(&self, doc: &Document, row: u16, column: u16) -> Option<usize> {
235 self.text_pos_at_screen_coords(&doc.text().slice(..), row, column, doc.tab_width())
220 self.text_pos_at_screen_coords(&doc.text().slice(..), row, column, doc.tab_width())
236 }
221 }
237 // pub fn traverse<F>(&self, text: RopeSlice, start: usize, end: usize, fun: F)
222 // pub fn traverse<F>(&self, text: RopeSlice, start: usize, end: usize, fun: F)