Skip to content

Commit 8a1bac1

Browse files
committed
Keypress handling and refactoring in Viewer::Tree
1 parent 634148b commit 8a1bac1

File tree

1 file changed

+98
-7
lines changed

1 file changed

+98
-7
lines changed

lib/Terminal/Widgets/Viewer/Tree.rakumod

Lines changed: 98 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class Terminal::Widgets::Viewer::Tree
5858
does Terminal::Widgets::Focusable {
5959
has VTree::Node $.root;
6060
has DisplayParent $.display-root is built(False);
61+
has DisplayNode $.current-node is built(False);
6162
has &.process-click;
6263

6364
has @!flat-node-cache;
@@ -97,6 +98,7 @@ class Terminal::Widgets::Viewer::Tree
9798
method set-root(VTree::Node:D $!root) { self!remap-root }
9899
method !remap-root() {
99100
$!display-root = DisplayParent.new(data => $!root, depth => 0);
101+
$!current-node = $!display-root;
100102
self.clear-caches;
101103
}
102104

@@ -152,10 +154,103 @@ class Terminal::Widgets::Viewer::Tree
152154
$caps.best-symbol-choice(%arrows)
153155
}
154156

155-
method line-to-display-node($line) {
157+
method line-to-display-node(UInt:D $line) {
156158
self.flat-node-cache[$line]
157159
}
158160

161+
method display-node-to-line($node) {
162+
self.flat-node-cache.first(* === $node, :k)
163+
}
164+
165+
method select-node($node) {
166+
$!current-node = $node;
167+
self.ensure-parents-expanded($node);
168+
$_($node) with &!process-click;
169+
170+
# XXXX: Ensure visible?
171+
}
172+
173+
method select-prev-node() {
174+
my $line = self.display-node-to-line($!current-node);
175+
return unless $line;
176+
177+
if self.line-to-display-node($line - 1) -> $node {
178+
self.select-node($node);
179+
self.ensure-y-span-visible($line - 1, $line);
180+
self.refresh-for-scroll;
181+
}
182+
}
183+
184+
method select-next-node() {
185+
my $line = self.display-node-to-line($!current-node);
186+
return unless $line.defined;
187+
188+
if self.line-to-display-node($line + 1) -> $node {
189+
self.select-node($node);
190+
self.ensure-y-span-visible($line, $line + 1);
191+
self.refresh-for-scroll;
192+
}
193+
}
194+
195+
method refresh-for-expand-change() {
196+
self.clear-caches;
197+
self.fix-scroll-maxes;
198+
self.refresh-for-scroll;
199+
}
200+
201+
method ensure-parents-expanded($node) {
202+
my $parent = $node.parent;
203+
my $changed = False;
204+
205+
while $parent {
206+
unless $parent.expanded {
207+
$parent.set-expanded(True);
208+
$changed = True;
209+
}
210+
$parent .= parent;
211+
}
212+
213+
self.refresh-for-expand-change if $changed;
214+
}
215+
216+
method set-node-expanded($node, Bool:D $expanded = True) {
217+
if $node ~~ DisplayParent && $node.expanded != $expanded {
218+
$node.set-expanded($expanded);
219+
self.refresh-for-expand-change;
220+
}
221+
}
222+
223+
method toggle-node-expanded($node) {
224+
if $node ~~ DisplayParent {
225+
$node.toggle-expanded;
226+
self.refresh-for-expand-change;
227+
}
228+
}
229+
230+
multi method handle-event(Terminal::Widgets::Events::KeyboardEvent:D
231+
$event where *.key.defined, AtTarget) {
232+
my constant %keymap =
233+
CursorDown => 'node-next',
234+
CursorUp => 'node-prev',
235+
CursorRight => 'node-expand',
236+
CursorLeft => 'node-collapse',
237+
Ctrl-M => 'node-toggle', # Enter
238+
Ctrl-I => 'focus-next', # Tab
239+
ShiftTab => 'focus-prev', # Shift-Tab is weird and special
240+
;
241+
242+
my $keyname = $event.keyname;
243+
with %keymap{$keyname} {
244+
when 'node-next' { self.select-next-node }
245+
when 'node-prev' { self.select-prev-node }
246+
when 'node-expand' { self.set-node-expanded($.current-node, True) }
247+
when 'node-collapse' { self.set-node-expanded($.current-node, False) }
248+
when 'node-toggle' { self.toggle-node-expanded($.current-node) }
249+
when 'focus-next' { self.focus-next }
250+
when 'focus-prev' { self.focus-prev }
251+
}
252+
}
253+
159254
multi method handle-event(Terminal::Widgets::Events::MouseEvent:D
160255
$event where !*.mouse.pressed, AtTarget) {
161256
# Take focus even if clicked on framing instead of content area
@@ -169,12 +264,8 @@ class Terminal::Widgets::Viewer::Tree
169264
my $clicked-line = $.y-scroll + $y;
170265
my $node = self.line-to-display-node($clicked-line);
171266

172-
if $node ~~ DisplayParent {
173-
$node.toggle-expanded;
174-
self.clear-caches;
175-
self.fix-scroll-maxes;
176-
self.refresh-for-scroll;
177-
}
267+
self.select-node($node);
268+
self.toggle-node-expanded($node);
178269

179270
if $node {
180271
$_($node) with &!process-click;

0 commit comments

Comments
 (0)