From 87723e508147c96f121cf2a9b544fd435810adc8 Mon Sep 17 00:00:00 2001 From: Oliver <480930+rivo@users.noreply.github.com> Date: Sat, 25 Mar 2023 22:05:32 +0100 Subject: [PATCH] Fixed the logic for triggering a TreeView's "changed" callback, allowing it to be triggered for calls to SetCurrentNode(), too. --- treeview.go | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/treeview.go b/treeview.go index 77bce5b..ae937ad 100644 --- a/treeview.go +++ b/treeview.go @@ -274,6 +274,9 @@ type TreeView struct { // The currently selected node or nil if no node is selected. currentNode *TreeNode + // The last note that was selected or nil of there is no such node. + lastNode *TreeNode + // The movement to be performed during the call to Draw(), one of the // constants defined above. movement int @@ -346,8 +349,8 @@ func (t *TreeView) GetRoot() *TreeNode { // selection will be changed to the top-most selectable and visible node. // // This function does NOT trigger the "changed" callback because the actual node -// that will be selected is not known until the tree is drawn. That is also when -// the "changed" callback will be triggered. +// that will be selected is not known until the tree is drawn. Triggering the +// "changed" callback is thus deferred until the next call to [TreeView.Draw]. func (t *TreeView) SetCurrentNode(node *TreeNode) *TreeView { t.currentNode = node return t @@ -404,8 +407,8 @@ func (t *TreeView) SetGraphicsColor(color tcell.Color) *TreeView { return t } -// SetChangedFunc sets the function which is called when the user navigates to -// a new tree node. +// SetChangedFunc sets the function which is called when the currently selected +// node changes, for example when the user navigates to a new tree node. func (t *TreeView) SetChangedFunc(handler func(node *TreeNode)) *TreeView { t.changed = handler return t @@ -458,9 +461,9 @@ func (t *TreeView) Move(offset int) *TreeView { } // process builds the visible tree, populates the "nodes" slice, and processes -// pending movement actions. Set "drawingAfter" to true if you know that [Draw] -// will be called immediately after this function (to avoid having [Draw] call -// it again). +// pending movement actions. Set "drawingAfter" to true if you know that +// [TreeView.Draw] will be called immediately after this function (to avoid +// having [TreeView.Draw] call it again). func (t *TreeView) process(drawingAfter bool) { t.stableNodes = drawingAfter _, _, _, height := t.GetInnerRect() @@ -544,26 +547,25 @@ func (t *TreeView) process(drawingAfter bool) { // Process selection. (Also trigger events if necessary.) if selectedIndex >= 0 { // Move the selection. - newSelectedIndex := selectedIndex switch t.movement { case treeMove: for t.step < 0 { // Going up. - index := newSelectedIndex + index := selectedIndex for index > 0 { index-- if t.nodes[index].selectable { - newSelectedIndex = index + selectedIndex = index break } } t.step++ } for t.step > 0 { // Going down. - index := newSelectedIndex + index := selectedIndex for index < len(t.nodes)-1 { index++ if t.nodes[index].selectable { - newSelectedIndex = index + selectedIndex = index break } } @@ -571,26 +573,20 @@ func (t *TreeView) process(drawingAfter bool) { } case treeParent: if parentSelectedIndex >= 0 { - newSelectedIndex = parentSelectedIndex + selectedIndex = parentSelectedIndex } case treeChild: - index := newSelectedIndex + index := selectedIndex for index < len(t.nodes)-1 { index++ if t.nodes[index].selectable && t.nodes[index].parent == t.nodes[selectedIndex] { - newSelectedIndex = index + selectedIndex = index } } } t.step = 0 - t.currentNode = t.nodes[newSelectedIndex] - if newSelectedIndex != selectedIndex { - t.movement = treeNone - if t.changed != nil { - t.changed(t.currentNode) - } - } - selectedIndex = newSelectedIndex + t.currentNode = t.nodes[selectedIndex] + t.movement = treeNone // Move selection into viewport. if t.movement != treeScroll { @@ -616,6 +612,12 @@ func (t *TreeView) process(drawingAfter bool) { t.currentNode = nil } } + + // Trigger "changed" callback. + if t.changed != nil && t.currentNode != nil && t.currentNode != t.lastNode { + t.changed(t.currentNode) + } + t.lastNode = t.currentNode } // Draw draws this primitive onto the screen.