diff options
author | Julian Eisel <julian@blender.org> | 2021-10-06 17:29:10 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2021-10-06 17:36:20 +0300 |
commit | 75fbf6f17e69ee9c6487173ae5957cfff5193d1f (patch) | |
tree | e27584eb4440d0280cd65a805c8a546966fb9d83 /source/blender | |
parent | 536109b4ec336e86de5a7e22e51804584bca74f5 (diff) |
Asset Browser: Show catalog add & delete icons on mouse hover (only)
Now the icons to add or delete catalogs are only shown when mouse hovering a
catalog item in the tree. This is convenient for quick creation of catalogs,
and doesn't require activating a catalog to edit it first.
Determining if a tree item is hovered isn't trivial actually. The UI tree-view
code has to find the matching tree-row button in the previous layout to do so,
since the new layout isn't calculated yet.
Diffstat (limited to 'source/blender')
5 files changed, 78 insertions, 9 deletions
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh index 8f8681896fe..7693a833210 100644 --- a/source/blender/editors/include/UI_tree_view.hh +++ b/source/blender/editors/include/UI_tree_view.hh @@ -185,6 +185,7 @@ class AbstractTreeView : public TreeViewItemContainer { const TreeViewItemContainer &old_items); static AbstractTreeViewItem *find_matching_child(const AbstractTreeViewItem &lookup_item, const TreeViewItemContainer &items); + /** * Items may want to do additional work when state changes. But these state changes can only be * reliably detected after the tree has completed reconstruction (see #is_reconstructed()). So @@ -290,6 +291,12 @@ class AbstractTreeViewItem : public TreeViewItemContainer { * can't be sure about the item state. */ bool is_active() const; + /** + * Can be called from the #AbstractTreeViewItem::build_row() implementation, but not earlier. The + * hovered state can't be queried reliably otherwise. + * Note that this does a linear lookup in the old block, so isn't too great performance-wise. + */ + bool is_hovered() const; void toggle_collapsed(); /** * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index 8e69ac40a34..5c06f8cfd13 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -1293,6 +1293,8 @@ void ui_interface_tag_script_reload_queries(void); void ui_block_free_views(struct uiBlock *block); uiTreeViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block, const uiTreeViewHandle *new_view); +uiButTreeRow *ui_block_view_find_treerow_in_old_block(const uiBlock *new_block, + const uiTreeViewItemHandle *new_item_handle); #ifdef __cplusplus } diff --git a/source/blender/editors/interface/interface_view.cc b/source/blender/editors/interface/interface_view.cc index b199ce9562e..8122b965892 100644 --- a/source/blender/editors/interface/interface_view.cc +++ b/source/blender/editors/interface/interface_view.cc @@ -106,26 +106,71 @@ static StringRef ui_block_view_find_idname(const uiBlock &block, const AbstractT return {}; } +static AbstractTreeView *ui_block_view_find_matching_in_old_block(const uiBlock &new_block, + const AbstractTreeView &new_view) +{ + uiBlock *old_block = new_block.oldblock; + if (!old_block) { + return nullptr; + } + + StringRef idname = ui_block_view_find_idname(new_block, new_view); + if (idname.is_empty()) { + return nullptr; + } + + LISTBASE_FOREACH (ViewLink *, old_view_link, &old_block->views) { + if (old_view_link->idname == idname) { + return get_view_from_link<AbstractTreeView>(*old_view_link); + } + } + + return nullptr; +} + uiTreeViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block, const uiTreeViewHandle *new_view_handle) { - const AbstractTreeView &needle_view = reinterpret_cast<const AbstractTreeView &>( - *new_view_handle); + BLI_assert(new_block && new_view_handle); + const AbstractTreeView &new_view = reinterpret_cast<const AbstractTreeView &>(*new_view_handle); + AbstractTreeView *old_view = ui_block_view_find_matching_in_old_block(*new_block, new_view); + return reinterpret_cast<uiTreeViewHandle *>(old_view); +} + +uiButTreeRow *ui_block_view_find_treerow_in_old_block(const uiBlock *new_block, + const uiTreeViewItemHandle *new_item_handle) +{ uiBlock *old_block = new_block->oldblock; if (!old_block) { return nullptr; } - StringRef idname = ui_block_view_find_idname(*new_block, needle_view); - if (idname.is_empty()) { + const AbstractTreeViewItem &new_item = *reinterpret_cast<const AbstractTreeViewItem *>( + new_item_handle); + const AbstractTreeView *old_tree_view = ui_block_view_find_matching_in_old_block( + *new_block, new_item.get_tree_view()); + if (!old_tree_view) { return nullptr; } - LISTBASE_FOREACH (ViewLink *, old_view_link, &old_block->views) { - if (old_view_link->idname == idname) { - return reinterpret_cast<uiTreeViewHandle *>( - get_view_from_link<AbstractTreeView>(*old_view_link)); + LISTBASE_FOREACH (uiBut *, old_but, &old_block->buttons) { + if (old_but->type != UI_BTYPE_TREEROW) { + continue; + } + uiButTreeRow *old_treerow_but = (uiButTreeRow *)old_but; + if (!old_treerow_but->tree_item) { + continue; + } + AbstractTreeViewItem &old_item = *reinterpret_cast<AbstractTreeViewItem *>( + old_treerow_but->tree_item); + /* Check if the row is from the expected tree-view. */ + if (&old_item.get_tree_view() != old_tree_view) { + continue; + } + + if (UI_tree_view_item_matches(new_item_handle, old_treerow_but->tree_item)) { + return old_treerow_but; } } diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc index d2971f791c2..7bcf679a5ea 100644 --- a/source/blender/editors/interface/tree_view.cc +++ b/source/blender/editors/interface/tree_view.cc @@ -385,6 +385,21 @@ bool AbstractTreeViewItem::is_active() const return is_active_; } +bool AbstractTreeViewItem::is_hovered() const +{ + BLI_assert_msg(get_tree_view().is_reconstructed(), + "State can't be queried until reconstruction is completed"); + BLI_assert_msg(tree_row_but_ != nullptr, + "Hovered state can't be queried before the tree row is being built"); + + const uiTreeViewItemHandle *this_handle = reinterpret_cast<const uiTreeViewItemHandle *>(this); + /* The new layout hasn't finished construction yet, so the final state of the button is unknown. + * Get the matching button from the previous redraw instead. */ + uiButTreeRow *old_treerow_but = ui_block_view_find_treerow_in_old_block(tree_row_but_->but.block, + this_handle); + return old_treerow_but && (old_treerow_but->but.flag & UI_ACTIVE); +} + bool AbstractTreeViewItem::is_collapsed() const { BLI_assert_msg(get_tree_view().is_reconstructed(), diff --git a/source/blender/editors/space_file/asset_catalog_tree_view.cc b/source/blender/editors/space_file/asset_catalog_tree_view.cc index 552a0a7acd0..fac38e71220 100644 --- a/source/blender/editors/space_file/asset_catalog_tree_view.cc +++ b/source/blender/editors/space_file/asset_catalog_tree_view.cc @@ -219,7 +219,7 @@ void AssetCatalogTreeViewItem::build_row(uiLayout &row) { ui::BasicTreeViewItem::build_row(row); - if (!is_active()) { + if (!is_hovered()) { return; } |