TreeView halp

I’m attempting to use a TreeView to display presets, and I have a bit of an odd query. You can move the selection item-by-item with the up and down arrow keys if the component has focus. However, I can’t for the life of me find any sort of callback where I’m notified that the selected item has been changed.

The way I see it, there are two options:

  1. Have a timer callback that checks to see if the selected item has changed, and changes the preset appropriately (this just sounds stupid now that I’ve typed it out; it made sense in my head though…)

  2. Listen for key up of both up and down arrow keys, and load whatever’s selected on key up. This doesn’t sound as stupid as option 1.

I feel like there’s an obvious callback that I can’t find, but I’d like to think I could be forgiven since TreeView and its accouterments aren’t the world’s most obvious family of classes. Anyone?

Use the timer approach with a callback when the tree has items selected. It’s clean and simple.

struct T : Timer
{
    using Callback = std::function<void(bool)>;
    T(TreeView& tv, Callback cb ) : treeView(tv), f( std::move(cb) ) { startTimerHz(20); } 
    ~T() override { stopTimer(); }
    void timerCallback() override
    {
        if( f ) 
            f( treeView.getNumSelectedItems() > 0 );
    }
private:
    TreeView& treeView;
    Callback f;
    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(T)
};

tested extensively here: https://gumroad.com/l/TaskQueueApp

your callback can call treeView.getSelectedItem(x) to get your selected preset.

Easy Breezy Lemon Squeezy!!

1 Like

I would not have expected that to be the answer. Whelp, if it works, it works.

1 Like

Why not? What about that solution made you say “this sounds stupid”? (per your original post)

I just assumed there was a callback happening somewhere I hadn’t found, because isSelected() changes based on keypresses.

ok.

well, when I figured out that solution, I didn’t spend too much time looking at the TreeView guts to see if there was any kind of callback. But I knew that TreeView::getNumSelected() could just be queried on a timer, soo… K.I.S.S., right?

querying a public member repeatedly is pretty simple in my view!

Especially if it’s just a comparator. Well, nothing to it but to do it. Thanks for the tip.

1 Like

np, glad to help. If someone knows of another way to solve this that does involve a TreeView callback, I’d love to know about it.

The TreeViewItem has a callback itemSelectionChanged (bool isNowSelected).

So in your derived TreeViewItem (that you have to inherit anyway) you can add a ChangeBroadcaster and make your TreeView or whatever you want to trigger the corresponding ChangeListener.
That’s how the FileTreeComponent does it (well, without the ChangeListener, but that’s easier IMHO)

3 Likes

Apologies to matkatmusic, but Daniel’s solution is what I was looking for. Don’t know how I missed it. I must have read past it 30 times. Hashtag old AF.

(Bonus: it works for both mouse clicks and keypresses. So I got to get rid of my isClicked override.)

2 Likes

lol you and I both missed it because it’s a member function of TreeViewItem, not TreeView.

This is something that might be worth a mention in the doc for TreeView, perhaps in the form of a short code example

More important than the docs would be the demo code. It sucks, because it’s all one-way, interactions telling the TreeView and Item what to do; there’s almost nothing in the code for getting information out of the TreeView. Since the demo code is the logical place to start for approaching these meta-Components and figuring out how they work, it would stand to reason that the demo code should, you know, do something.

(See also: the various list views, which exhibit the same “look at what we made! It doesn’t matter how it works!” approach.)

2 Likes

I think the mindset was always to extract data from the items themselves via inheritance, and not via the container (listbox vs listboxmodel, treeview vs treeviewitem, etc)

Hover, if you would connect two views to a model, I would place the selection rather towards the view than the model, but that is a case that can be argued…

Aren’t the items part of the view and not the model?

The TreeView doesn’t follow the MVC paradigm, since the TreeViewItem is owned by the TreeView, so it cannot be used by different TreeViews anyway.

This is a rather theoretical discussion, and I don’t design the API, so I cannot comment on that.
I am just using what is there and am happy to share ideas, how to achieve your goals.