Skip to content

Commit 9c37cd1

Browse files
committed
wip scroll using arrow keys
1 parent 3a32243 commit 9c37cd1

File tree

2 files changed

+129
-46
lines changed

2 files changed

+129
-46
lines changed

src/array_table.rs

Lines changed: 101 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ pub struct Column<'col> {
3838
pub id: usize,
3939
}
4040

41-
impl <'col> Hash for Column<'col> {
41+
impl<'col> Hash for Column<'col> {
4242
fn hash<H: Hasher>(&self, state: &mut H) {
4343
self.name.hash(state)
4444
}
4545
}
4646

47-
impl <'col>Column<'col> {
47+
impl<'col> Column<'col> {
4848
pub fn new(name: String, value_type: ValueType) -> Self {
4949
Self {
5050
name: Cow::from(name),
@@ -57,22 +57,22 @@ impl <'col>Column<'col> {
5757
}
5858
}
5959

60-
impl <'col>Eq for Column<'col> {}
60+
impl<'col> Eq for Column<'col> {}
6161

62-
impl <'col>PartialEq<Self> for Column<'col> {
62+
impl<'col> PartialEq<Self> for Column<'col> {
6363
fn eq(&self, other: &Self) -> bool {
6464
self.name.eq(&other.name)
6565
}
6666
}
6767

6868

69-
impl <'col>PartialOrd<Self> for Column<'col> {
69+
impl<'col> PartialOrd<Self> for Column<'col> {
7070
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
7171
Some(self.cmp(other))
7272
}
7373
}
7474

75-
impl <'col>Ord for Column<'col> {
75+
impl<'col> Ord for Column<'col> {
7676
fn cmp(&self, other: &Self) -> Ordering {
7777
match other.seen_count.cmp(&self.seen_count) {
7878
Ordering::Equal => other.order.cmp(&self.order),
@@ -127,14 +127,24 @@ pub struct ArrayTable<'array> {
127127
pub matching_column_selected: usize,
128128
pub scroll_to_column: String,
129129
pub scroll_to_row: String,
130+
pub scroll_to_row_number: usize,
131+
pub scroll_to_column_number: usize,
130132
pub scroll_to_row_mode: ScrollToRowMode,
131133
pub focused_cell: Option<CellLocation>,
132134

135+
// Visibility information
136+
pub first_visible_index: usize,
137+
pub last_visible_index: usize,
138+
pub first_visible_offset: f32,
139+
pub last_visible_offset: f32,
140+
133141
// Handle interaction
134142
pub next_frame_reset_scroll: bool,
135143
pub changed_scroll_to_column_value: bool,
136144
pub changed_matching_column_selected: bool,
137145
pub changed_matching_row_selected: bool,
146+
pub changed_arrow_horizontal_scroll: bool,
147+
pub changed_arrow_vertical_scroll: bool,
138148

139149
#[cfg(not(target_arch = "wasm32"))]
140150
pub changed_scroll_to_row_value: Option<std::time::Instant>,
@@ -149,7 +159,7 @@ pub struct ArrayTable<'array> {
149159
}
150160

151161

152-
impl <'array>super::View<ArrayResponse> for ArrayTable<'array> {
162+
impl<'array> super::View<ArrayResponse> for ArrayTable<'array> {
153163
fn ui(&mut self, ui: &mut egui::Ui) -> ArrayResponse {
154164
use egui_extras::{Size, StripBuilder};
155165
let mut array_response = ArrayResponse::default();
@@ -189,6 +199,15 @@ impl <'array>super::View<ArrayResponse> for ArrayTable<'array> {
189199
}
190200
}
191201

202+
if self.changed_arrow_horizontal_scroll {
203+
self.changed_arrow_horizontal_scroll = false;
204+
if !(self.first_visible_index < self.scroll_to_column_number && self.scroll_to_column_number < self.last_visible_index) {
205+
if let Some(offset) = self.columns_offset.get(self.scroll_to_column_number) {
206+
scroll_to_x = Some(*offset);
207+
}
208+
}
209+
}
210+
192211
if self.changed_matching_column_selected {
193212
self.changed_matching_column_selected = false;
194213
if !self.matching_columns.is_empty() {
@@ -239,7 +258,7 @@ impl Hash for CachePointerKey {
239258
}
240259
}
241260

242-
impl <'array> crate::components::cache::ComputerMut<(&Column<'array>, &String), &Vec<JsonArrayEntries<String>>, IndexSet<String>> for CacheFilterOptions {
261+
impl<'array> crate::components::cache::ComputerMut<(&Column<'array>, &String), &Vec<JsonArrayEntries<String>>, IndexSet<String>> for CacheFilterOptions {
243262
fn compute(&mut self, (column, parent_pointer): (&Column<'array>, &String), nodes: &Vec<JsonArrayEntries<String>>) -> IndexSet<String> {
244263
let mut unique_values = IndexSet::new();
245264
if ArrayTable::is_filterable(column) {
@@ -272,7 +291,7 @@ impl <'array> crate::components::cache::ComputerMut<(&Column<'array>, &String),
272291
}
273292

274293

275-
impl <'array>crate::components::cache::ComputerMut<CachePointerKey, &ArrayTable<'array>, Option<usize>> for CacheGetPointer {
294+
impl<'array> crate::components::cache::ComputerMut<CachePointerKey, &ArrayTable<'array>, Option<usize>> for CacheGetPointer {
276295
fn compute(&mut self, cache_pointer_key: CachePointerKey, table: &ArrayTable<'array>) -> Option<usize> {
277296
let columns = if cache_pointer_key.pinned_column_table { &table.column_pinned } else { &table.column_selected };
278297
ArrayTable::get_pointer_index(&table.parent_pointer, columns, &table.nodes()[cache_pointer_key.row_index].entries(), cache_pointer_key.index, cache_pointer_key.row_index)
@@ -281,7 +300,7 @@ impl <'array>crate::components::cache::ComputerMut<CachePointerKey, &ArrayTable<
281300

282301
pub const NON_NULL_FILTER_VALUE: &str = "__non_null";
283302

284-
impl <'array>ArrayTable<'array> {
303+
impl<'array> ArrayTable<'array> {
285304
pub fn new(parse_result: Option<ParseResult<String>>, nodes: Vec<JsonArrayEntries<String>>, all_columns: Vec<Column<'array>>, depth: u8, parent_pointer: PointerKey) -> Self {
286305
let last_parsed_max_depth = parse_result.as_ref().map_or(depth, |p| p.parsing_max_depth);
287306
Self {
@@ -311,13 +330,21 @@ impl <'array>ArrayTable<'array> {
311330
columns_filter: HashMap::new(),
312331
scroll_to_row_mode: ScrollToRowMode::RowNumber,
313332
scroll_to_row: "".to_string(),
333+
scroll_to_row_number: 0,
334+
scroll_to_column_number: 0,
314335
changed_scroll_to_row_value: None,
315336
changed_matching_row_selected: false,
316337
changed_matching_column_selected: false,
338+
changed_arrow_horizontal_scroll: false,
339+
changed_arrow_vertical_scroll: false,
317340
editing_index: RefCell::new(None),
318341
editing_value: RefCell::new(String::new()),
319342
is_sub_table: false,
320343
focused_cell: None,
344+
first_visible_index: 0,
345+
last_visible_index: 0,
346+
first_visible_offset: 0.0,
347+
last_visible_offset: 0.0,
321348
cache: Default::default(),
322349
opened_windows: Default::default(),
323350
search_replace_panel: Default::default(),
@@ -470,6 +497,10 @@ impl <'array>ArrayTable<'array> {
470497
}
471498
}
472499
}
500+
if self.changed_arrow_vertical_scroll {
501+
self.changed_arrow_vertical_scroll = false;
502+
table = table.scroll_to_row(self.scroll_to_row_number, Some(Align::Center));
503+
}
473504
if self.changed_matching_row_selected {
474505
self.changed_matching_row_selected = false;
475506
table = table.scroll_to_row(self.matching_rows[self.matching_row_selected], Some(Align::Center));
@@ -503,19 +534,23 @@ impl <'array>ArrayTable<'array> {
503534
} else {
504535
None
505536
};
506-
let table_scroll_output = table
537+
let table_response = table
507538
.header(text_height * 2.0, |header| {
508539
self.header(pinned_column_table, header);
509540
})
510541
.body(self.hovered_row_index, search_highlight_row, self.focused_cell, |body| {
511542
self.body(text_height, pinned_column_table, &mut array_response, request_repaint, body);
512543
});
513-
544+
let table_scroll_output = table_response.scroll_area_output;
514545
if self.scroll_y != table_scroll_output.state.offset.y {
515546
self.scroll_y = table_scroll_output.state.offset.y;
516547
}
517548
if !pinned_column_table {
518-
self.columns_offset = table_scroll_output.inner;
549+
self.columns_offset = table_response.columns_offset;
550+
self.first_visible_index = table_response.first_visible_index;
551+
self.first_visible_offset = table_response.first_visible_offset;
552+
self.last_visible_index = table_response.last_visible_index;
553+
self.last_visible_offset = table_response.last_visible_offset;
519554
}
520555
if request_repaint {
521556
ui.ctx().request_repaint();
@@ -682,7 +717,7 @@ impl <'array>ArrayTable<'array> {
682717
*self.editing_value.borrow_mut() = value.clone();
683718
*editing_index = Some((col_index, row_index, pinned_column_table));
684719
}
685-
if response.secondary_clicked() {
720+
if response.secondary_clicked() || response.clicked() {
686721
focused_cell = Some(CellLocation { column_index: col_index, row_index: table_row_index, is_pinned_column_table: pinned_column_table });
687722
focused_changed = true;
688723
}
@@ -750,12 +785,6 @@ impl <'array>ArrayTable<'array> {
750785
}
751786
});
752787

753-
if let Some(focused_cell_location) = self.focused_cell {
754-
if focused_cell_location.is_pinned_column_table == pinned_column_table && focused_cell_location.row_index == table_row_index && focused_cell_location.column_index == col_index && !response.context_menu_opened() {
755-
focused_cell = None;
756-
focused_changed = true;
757-
}
758-
}
759788
if response.hovered() {
760789
ui.ctx().set_cursor_icon(CursorIcon::Cell);
761790
}
@@ -780,7 +809,7 @@ impl <'array>ArrayTable<'array> {
780809
*editing_index = Some((col_index, row_index, pinned_column_table));
781810
}
782811

783-
if response.secondary_clicked() {
812+
if response.secondary_clicked() || response.clicked() {
784813
focused_cell = Some(CellLocation { column_index: col_index, row_index: table_row_index, is_pinned_column_table: pinned_column_table });
785814
focused_changed = true;
786815
}
@@ -818,12 +847,7 @@ impl <'array>ArrayTable<'array> {
818847
}
819848
});
820849

821-
if let Some(focused_cell_location) = self.focused_cell {
822-
if focused_cell_location.is_pinned_column_table == pinned_column_table && focused_cell_location.row_index == table_row_index && focused_cell_location.column_index == col_index && !response.context_menu_opened() {
823-
focused_cell = None;
824-
focused_changed = true;
825-
}
826-
}
850+
827851
if response.hovered() {
828852
ui.ctx().set_cursor_icon(CursorIcon::Cell);
829853
}
@@ -906,22 +930,25 @@ impl <'array>ArrayTable<'array> {
906930
let substring_len = substring_len + (i.checked_ilog10().unwrap_or(0) + 1) as usize;
907931
let new_prefix = concat_string!(self.parent_pointer.pointer, "/", (i+1).to_string());
908932
self.nodes[i].entries.iter_mut().for_each(|e| {
909-
e.pointer.pointer = concat_string!(new_prefix, e.pointer.pointer[substring_len..]);
933+
e.pointer.pointer = concat_string!(new_prefix, e.pointer.pointer[substring_len..]);
910934
})
911935
}
912936
let new_entry_pointer = concat_string!(self.parent_pointer.pointer, "/", new_index.to_string());
913937
self.nodes.insert(new_index, JsonArrayEntries {
914938
entries: vec![
915939
row_number_entry(new_index, 0, new_entry_pointer.as_str()),
916-
FlatJsonValue { pointer: PointerKey {
917-
pointer: new_entry_pointer,
918-
value_type: ValueType::Object(true, 0),
919-
depth,
920-
position: 0,
921-
column_id: 0,
922-
}, value: Some("{}".to_string()) }
940+
FlatJsonValue {
941+
pointer: PointerKey {
942+
pointer: new_entry_pointer,
943+
value_type: ValueType::Object(true, 0),
944+
depth,
945+
position: 0,
946+
column_id: 0,
947+
},
948+
value: Some("{}".to_string())
949+
}
923950
],
924-
index: new_index
951+
index: new_index,
925952
});
926953
self.filtered_nodes.insert(table_row_index + above_or_below as usize, new_index);
927954
self.cache.borrow_mut().evict();
@@ -966,7 +993,7 @@ impl <'array>ArrayTable<'array> {
966993

967994
let value_changed = Self::update_row(&mut self.nodes[row_index].entries, updated_entry, self.is_sub_table, self.last_parsed_max_depth);
968995
if value_changed {
969-
self.cache.borrow_mut().evict();
996+
self.cache.borrow_mut().evict();
970997
}
971998
value_changed
972999
}
@@ -1100,6 +1127,40 @@ impl <'array>ArrayTable<'array> {
11001127
fn handle_shortcut(&mut self, ui: &mut Ui, array_response: &mut ArrayResponse) {
11011128
let mut copied_value = None;
11021129
ui.input_mut(|i| {
1130+
if let Some(focused_cell) = self.focused_cell.as_mut() {
1131+
if i.key_pressed(Key::ArrowLeft) {
1132+
if !focused_cell.is_pinned_column_table && focused_cell.column_index > 0 {
1133+
focused_cell.column_index = focused_cell.column_index - 1;
1134+
self.scroll_to_column_number = focused_cell.column_index;
1135+
self.changed_arrow_horizontal_scroll = true;
1136+
} else if focused_cell.is_pinned_column_table && focused_cell.column_index > 1 {
1137+
focused_cell.column_index = focused_cell.column_index - 1;
1138+
}
1139+
}
1140+
if i.key_pressed(Key::ArrowRight) {
1141+
if !focused_cell.is_pinned_column_table && focused_cell.column_index < self.column_selected.len() - 1 {
1142+
focused_cell.column_index = focused_cell.column_index + 1;
1143+
self.scroll_to_column_number = focused_cell.column_index;
1144+
self.changed_arrow_horizontal_scroll = true;
1145+
} else if focused_cell.is_pinned_column_table && focused_cell.column_index < self.column_pinned.len() - 1 {
1146+
focused_cell.column_index = focused_cell.column_index + 1;
1147+
}
1148+
}
1149+
if i.key_pressed(Key::ArrowUp) {
1150+
if focused_cell.row_index > 0 {
1151+
focused_cell.row_index = focused_cell.row_index - 1;
1152+
self.scroll_to_row_number = focused_cell.row_index;
1153+
self.changed_arrow_vertical_scroll = true;
1154+
}
1155+
}
1156+
if i.key_pressed(Key::ArrowDown) {
1157+
if focused_cell.row_index < self.nodes.len() - 1 {
1158+
focused_cell.row_index = focused_cell.row_index + 1;
1159+
self.scroll_to_row_number = focused_cell.row_index;
1160+
self.changed_arrow_vertical_scroll = true;
1161+
}
1162+
}
1163+
}
11031164
if i.consume_shortcut(&SHORTCUT_DELETE) {
11041165
i.events.push(egui::Event::Key {
11051166
key: Key::Delete,
@@ -1116,15 +1177,15 @@ impl <'array>ArrayTable<'array> {
11161177
for event in i.events.iter().filter(|e| match e {
11171178
egui::Event::Copy => hovered_cell.is_some(),
11181179
egui::Event::Paste(_) => hovered_cell.is_some(),
1119-
egui::Event::Key{key: Key::Delete, ..} => hovered_cell.is_some(),
1180+
egui::Event::Key { key: Key::Delete, .. } => hovered_cell.is_some(),
11201181
_ => false,
11211182
}) {
11221183
let cell_location = hovered_cell.unwrap();
11231184
let row_index = self.filtered_nodes[cell_location.row_index];
11241185
let index = self.get_pointer_index_from_cache(cell_location.is_pinned_column_table, &&self.nodes[row_index], cell_location.column_index);
11251186

11261187
match event {
1127-
egui::Event::Key{key: Key::Delete, ..} => {
1188+
egui::Event::Key { key: Key::Delete, .. } => {
11281189
let columns = self.columns(cell_location.is_pinned_column_table);
11291190
let pointer = Self::pointer_key(&self.parent_pointer.pointer, row_index, columns.get(cell_location.column_index).as_ref().unwrap().name.as_str());
11301191
let flat_json_value = FlatJsonValue::<String> {
@@ -1148,7 +1209,7 @@ impl <'array>ArrayTable<'array> {
11481209
};
11491210
match flat_json_value.pointer.value_type {
11501211
// When we paste an object it should not be considered as parsed
1151-
ValueType::Object(..) => { flat_json_value.pointer.value_type = ValueType::Object(false,0) }
1212+
ValueType::Object(..) => { flat_json_value.pointer.value_type = ValueType::Object(false, 0) }
11521213
_ => {}
11531214
}
11541215
self.edit_cell(array_response, flat_json_value, row_index);

0 commit comments

Comments
 (0)