densa_widgets/grid/
selection.rs1use std::ops::Range;
4
5use densa_grid::{CellText, GridModel, Palette};
6use densa_ui::{ActionKind, EventCx};
7
8use super::DataGrid;
9
10impl<M: GridModel> DataGrid<M> {
11 pub fn selected_rows(&self) -> Range<usize> {
14 let rows = self.model.rows();
15 if self.all {
16 return 0..rows;
17 }
18 let Some(focus) = self.selected() else {
19 return 0..0;
20 };
21 let anchor = self.anchor.map_or(focus, |a| a.row);
22 let end = (anchor.max(focus) + 1).min(rows);
24 anchor.min(focus).min(end)..end
25 }
26
27 pub fn select_rows(&mut self, cx: &mut EventCx<'_>, anchor: usize, row: usize) {
31 let Some(last) = self.model.rows().checked_sub(1) else {
32 return;
33 };
34 self.all = false;
35 self.anchor = None;
36 self.select(cx, Some(row.min(last)));
37 self.anchor = Some(self.selection_of(anchor.min(last)));
38 }
39
40 pub fn select_all(&mut self, cx: &mut EventCx<'_>) {
43 self.all = true;
44 cx.request_paint();
45 }
46
47 pub fn copy(&mut self, cx: &mut EventCx<'_>) -> bool {
53 self.catch_up();
54 if self.selected_rows().is_empty() {
55 return false;
56 }
57 let text = self.selected_text(&super::palette(cx.theme()));
58 cx.clipboard().set_text(&text).is_ok()
59 }
60
61 pub fn selected_text(&mut self, palette: &Palette) -> String {
66 self.catch_up();
67 let columns = self.model.columns().len();
68 let mut out = String::new();
69 let mut cell = CellText::new();
70 for (index, row) in self.selected_rows().enumerate() {
71 if index > 0 {
72 out.push('\n');
73 }
74 for column in 0..columns {
75 if column > 0 {
76 out.push('\t');
77 }
78 cell.clear();
79 self.model.cell(row, column, &mut cell, palette);
80 out.extend(cell.as_str().chars().map(|c| match c {
81 '\t' | '\n' | '\r' => ' ',
82 c => c,
83 }));
84 }
85 }
86 out
87 }
88
89 fn catch_up(&mut self) {
91 self.model.prepare();
92 self.follow_model();
93 self.clamp();
94 }
95
96 pub(super) fn select_row(&mut self, cx: &mut EventCx<'_>, row: usize) {
98 self.anchor = None;
99 self.all = false;
100 self.move_selection(cx, row);
101 }
102
103 pub(super) fn extend_to(&mut self, cx: &mut EventCx<'_>, row: usize) {
106 self.all = false;
107 if self.anchor.is_none() {
108 self.anchor = Some(self.selected.unwrap_or_else(|| self.selection_of(row)));
109 }
110 self.move_selection(cx, row);
111 }
112
113 fn move_selection(&mut self, cx: &mut EventCx<'_>, row: usize) {
115 if self.selected() != Some(row) {
116 self.selected = Some(self.selection_of(row));
117 cx.emit(ActionKind::Selected(row));
118 }
119 self.reveal_row(row);
120 cx.request_paint();
121 }
122}