on master help sign in
ui: Redo selection rendering.
commit8e1a59c1408597484aeff7f96a09f1a1d10c76f6 authorBlaž Hrastnik <blaz@mxxn.io> dateWed 17 Feb 2021, 14:41 (6 years ago) parentc408e7e
1 file changed+91−43
helix-term/src/ui/editor.rs+91−43
helix-term/src/ui/editor.rs+91−43
@@ -100,20 +100,6 @@ impl EditorView {
100100 let mut spans = Vec::new();
101101 let mut visual_x = 0;
102102 let mut line = 0u16;
103− let visible_selections: Vec<Range> = if is_focused {
104− view.doc
105− .state
106− .selection()
107− .ranges()
108− .iter()
109− // TODO: limit selection to one in viewport
110− // .filter(|range| !range.is_empty()) // && range.overlaps(&Range::new(start, end + 1))
111− .copied()
112− .collect()
113− } else {
114− // don't render selections on unfocused windows
115− Vec::new()
116− };
117103
118104 'outer: for event in highlights {
119105 match event.unwrap() {
@@ -174,26 +160,6 @@ impl EditorView {
174160 let grapheme = Cow::from(grapheme);
175161 let width = grapheme_width(&grapheme) as u16;
176162
177− // TODO: this should really happen as an after pass
178− let style = if visible_selections
179− .iter()
180− .any(|range| range.contains(char_index))
181− {
182− // cedar
183− style.clone().bg(Color::Rgb(128, 47, 0))
184− } else {
185− style
186− };
187−
188− let style = if visible_selections
189− .iter()
190− .any(|range| range.head == char_index)
191− {
192− style.clone().bg(Color::Rgb(255, 255, 255))
193− } else {
194− style
195− };
196−
197163 // ugh, improve with a traverse method
198164 // or interleave highlight spans with selection and diagnostic spans
199165 let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| {
@@ -206,8 +172,6 @@ impl EditorView {
206172 style
207173 };
208174
209− // TODO: paint cursor heads except primary
210−
211175 surface.set_string(
212176 viewport.x + visual_x,
213177 viewport.y + line,
@@ -224,18 +188,102 @@ impl EditorView {
224188 }
225189 }
226190
191+ // render selections
192+
193+ if is_focused {
194+ let text = view.doc.text().slice(..);
195+ let screen = {
196+ let start = text.line_to_char(view.first_line);
197+ let end = text.line_to_char(last_line + 1);
198+ Range::new(start, end)
199+ };
200+ let cursor_style = Style::default().bg(Color::Rgb(255, 255, 255));
201+
202+ // cedar
203+ let selection_style = Style::default().bg(Color::Rgb(128, 47, 0));
204+
205+ for selection in view
206+ .doc
207+ .state
208+ .selection()
209+ .ranges()
210+ .iter()
211+ .filter(|range| range.overlaps(&screen))
212+ {
213+ // TODO: render also if only one of the ranges is in viewport
214+ let mut start = view.screen_coords_at_pos(&text, selection.anchor);
215+ let mut end = view.screen_coords_at_pos(&text, selection.head);
216+
217+ // cursor
218+ if let Some(end) = end {
219+ surface.set_style(
220+ Rect::new(
221+ viewport.x + end.col as u16,
222+ viewport.y + end.row as u16,
223+ 1,
224+ 1,
225+ ),
226+ cursor_style,
227+ );
228+ }
229+
230+ if selection.head < selection.anchor {
231+ std::mem::swap(&mut start, &mut end);
232+ }
233+ let start = start.unwrap_or_else(|| Position::new(0, 0));
234+ let end = end.unwrap_or_else(|| {
235+ Position::new(viewport.height as usize, viewport.width as usize)
236+ });
237+
238+ if start.row == end.row {
239+ surface.set_style(
240+ Rect::new(
241+ viewport.x + start.col as u16,
242+ viewport.y + start.row as u16,
243+ (end.col - start.col) as u16,
244+ 1,
245+ ),
246+ selection_style,
247+ );
248+ } else {
249+ surface.set_style(
250+ Rect::new(
251+ viewport.x + start.col as u16,
252+ viewport.y + start.row as u16,
253+ // text.line(view.first_line).len_chars() as u16 - start.col as u16,
254+ viewport.width - start.col as u16,
255+ 1,
256+ ),
257+ selection_style,
258+ );
259+ for i in start.row + 1..end.row {
260+ surface.set_style(
261+ Rect::new(
262+ viewport.x,
263+ viewport.y + i as u16,
264+ // text.line(view.first_line + i).len_chars() as u16,
265+ viewport.width,
266+ 1,
267+ ),
268+ selection_style,
269+ );
270+ }
271+ surface.set_style(
272+ Rect::new(viewport.x, viewport.y + end.row as u16, end.col as u16, 1),
273+ selection_style,
274+ );
275+ }
276+ }
277+ }
278+
279+ // render gutters
280+
227281 let style: Style = theme.get("ui.linenr");
228282 let warning: Style = theme.get("warning");
229283 let last_line = view.last_line();
230284 for (i, line) in (view.first_line..last_line).enumerate() {
231285 if view.doc.diagnostics.iter().any(|d| d.line == line) {
232− surface.set_stringn(
233− viewport.x + 0 - OFFSET,
234− viewport.y + i as u16,
235− "●",
236− 1,
237− warning,
238− );
286+ surface.set_stringn(viewport.x - OFFSET, viewport.y + i as u16, "●", 1, warning);
239287 }
240288
241289 surface.set_stringn(