[Bf-blender-cvs] [539575b585a] master: Assets: Support Renaming Catalogs in the UI

Julian Eisel noreply at git.blender.org
Wed Oct 6 14:25:38 CEST 2021


Commit: 539575b585a018eabda9137d724967692433165a
Author: Julian Eisel
Date:   Wed Oct 6 14:18:12 2021 +0200
Branches: master
https://developer.blender.org/rB539575b585a018eabda9137d724967692433165a

Assets: Support Renaming Catalogs in the UI

Catalogs can now be renamed by double clicking them in the Asset
Browser. This is mostly done through the tree-view API, the asset
specific code is very little.

There is some polish left to be done here, e.g. the double click
currently also collapses/uncollapses and activates the clicked item. And
the rename button takes the full width of the row. But addressing these
is better done as part of some other behavioral changes that are planned
anyway.

===================================================================

M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/include/UI_tree_view.hh
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/tree_view.cc
M	source/blender/editors/space_file/asset_catalog_tree_view.cc

===================================================================

diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index f642895f64e..e8b71a41439 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -2770,6 +2770,8 @@ char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item,
                                      const struct bContext *C,
                                      const struct wmDrag *drag,
                                      const struct wmEvent *event);
+bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle);
+void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle);
 
 uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const struct ARegion *region, int x, int y);
 
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index dbafd1b3a2b..51737067648 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -23,10 +23,13 @@
 
 #pragma once
 
+#include <array>
 #include <functional>
 #include <memory>
 #include <string>
 
+#include "DNA_defs.h"
+
 #include "BLI_function_ref.hh"
 #include "BLI_vector.hh"
 
@@ -144,8 +147,14 @@ class TreeViewLayoutBuilder {
  * \{ */
 
 class AbstractTreeView : public TreeViewItemContainer {
+  friend AbstractTreeViewItem;
   friend TreeViewBuilder;
-  friend TreeViewLayoutBuilder;
+
+  /**
+   * Only one item can be renamed at a time. So the tree is informed about the renaming state to
+   * enforce that.
+   */
+  std::unique_ptr<std::array<char, MAX_NAME>> rename_buffer_;
 
   bool is_reconstructed_ = false;
 
@@ -154,6 +163,8 @@ class AbstractTreeView : public TreeViewItemContainer {
 
   void foreach_item(ItemIterFn iter_fn, IterOptions options = IterOptions::None) const;
 
+  /** Only one item can be renamed at a time. */
+  bool is_renaming() const;
   /**
    * Check if the tree is fully (re-)constructed. That means, both #build_tree() and
    * #update_from_old() have finished.
@@ -198,6 +209,7 @@ class AbstractTreeView : public TreeViewItemContainer {
  */
 class AbstractTreeViewItem : public TreeViewItemContainer {
   friend class AbstractTreeView;
+  friend class TreeViewLayoutBuilder;
 
  public:
   using IsActiveFn = std::function<bool()>;
@@ -205,12 +217,15 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
  private:
   bool is_open_ = false;
   bool is_active_ = false;
+  bool is_renaming_ = false;
 
   IsActiveFn is_active_fn_;
 
  protected:
   /** This label is used for identifying an item (together with its parent's labels). */
   std::string label_{};
+  /** Every item gets a button of type during the layout building #UI_BTYPE_TREEROW. */
+  uiButTreeRow *tree_row_but_ = nullptr;
 
  public:
   virtual ~AbstractTreeViewItem() = default;
@@ -234,6 +249,19 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
   virtual std::string drop_tooltip(const bContext &C,
                                    const wmDrag &drag,
                                    const wmEvent &event) const;
+  /**
+   * Queries if the tree-view item supports renaming in principle. Renaming may still fail, e.g. if
+   * another item is already being renamed.
+   */
+  virtual bool can_rename() const;
+  /**
+   * Try renaming the item, or the data it represents. Can assume
+   * #AbstractTreeViewItem::can_rename() returned true. Sub-classes that override this should
+   * usually call this, unless they have a custom #AbstractTreeViewItem.matches().
+   *
+   * \return True if the renaming was successful.
+   */
+  virtual bool rename(StringRefNull new_name);
 
   /**
    * Copy persistent state (e.g. is-collapsed flag, selection, etc.) from a matching item of
@@ -250,7 +278,11 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
    */
   virtual bool matches(const AbstractTreeViewItem &other) const;
 
+  void begin_renaming();
+  void end_renaming();
+
   const AbstractTreeView &get_tree_view() const;
+  AbstractTreeView &get_tree_view();
   int count_parents() const;
   void deactivate();
   /**
@@ -266,6 +298,8 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
   bool is_collapsed() const;
   void set_collapsed(bool collapsed);
   bool is_collapsible() const;
+  bool is_renaming() const;
+
   void ensure_parents_uncollapsed();
 
  protected:
@@ -278,8 +312,14 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
   void activate();
 
  private:
+  static void rename_button_fn(bContext *, void *, char *);
+  static AbstractTreeViewItem *find_tree_item_from_rename_button(const uiBut &but);
+  static void tree_row_click_fn(struct bContext *, void *, void *);
+
   /** See #AbstractTreeView::change_state_delayed() */
   void change_state_delayed();
+  void add_treerow_button(uiBlock &block);
+  void add_rename_button(uiBlock &block);
 };
 
 /** \} */
@@ -304,8 +344,6 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
   void on_activate(ActivateFn fn);
 
  protected:
-  /** Created in the #build() function. */
-  uiButTreeRow *tree_row_but_ = nullptr;
   /**
    * Optionally passed to the #BasicTreeViewItem constructor. Called when activating this tree
    * view item. This way users don't have to sub-class #BasicTreeViewItem, just to implement
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 6ee563003ef..f73420b3668 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4822,6 +4822,24 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons
   return WM_UI_HANDLER_CONTINUE;
 }
 
+static int ui_do_but_TREEROW(bContext *C,
+                             uiBut *but,
+                             uiHandleButtonData *data,
+                             const wmEvent *event)
+{
+  uiButTreeRow *tree_row_but = (uiButTreeRow *)but;
+  BLI_assert(tree_row_but->but.type == UI_BTYPE_TREEROW);
+
+  if ((event->type == LEFTMOUSE) && (event->val == KM_DBL_CLICK)) {
+    button_activate_state(C, but, BUTTON_STATE_EXIT);
+
+    UI_tree_view_item_begin_rename(tree_row_but->tree_item);
+    return WM_UI_HANDLER_BREAK;
+  }
+
+  return ui_do_but_TOG(C, but, data, event);
+}
+
 static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event)
 {
   if (data->state == BUTTON_STATE_HIGHLIGHT) {
@@ -7989,10 +8007,12 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent *
     case UI_BTYPE_CHECKBOX:
     case UI_BTYPE_CHECKBOX_N:
     case UI_BTYPE_ROW:
-    case UI_BTYPE_TREEROW:
     case UI_BTYPE_DATASETROW:
       retval = ui_do_but_TOG(C, but, data, event);
       break;
+    case UI_BTYPE_TREEROW:
+      retval = ui_do_but_TREEROW(C, but, data, event);
+      break;
     case UI_BTYPE_SCROLL:
       retval = ui_do_but_SCROLL(C, block, but, data, event);
       break;
diff --git a/source/blender/editors/interface/tree_view.cc b/source/blender/editors/interface/tree_view.cc
index 8bd2be7dc77..8f272143b2c 100644
--- a/source/blender/editors/interface/tree_view.cc
+++ b/source/blender/editors/interface/tree_view.cc
@@ -20,6 +20,8 @@
 
 #include "DNA_userdef_types.h"
 
+#include "BKE_context.h"
+
 #include "BLT_translation.h"
 
 #include "interface_intern.h"
@@ -76,6 +78,11 @@ void AbstractTreeView::foreach_item(ItemIterFn iter_fn, IterOptions options) con
   foreach_item_recursive(iter_fn, options);
 }
 
+bool AbstractTreeView::is_renaming() const
+{
+  return rename_buffer_ != nullptr;
+}
+
 void AbstractTreeView::build_layout_from_tree(const TreeViewLayoutBuilder &builder)
 {
   uiLayout *prev_layout = builder.current_layout();
@@ -103,6 +110,13 @@ void AbstractTreeView::update_from_old(uiBlock &new_block)
   BLI_assert(old_view_handle);
 
   AbstractTreeView &old_view = reinterpret_cast<AbstractTreeView &>(*old_view_handle);
+
+  /* Update own persistent data. */
+  /* Keep the rename buffer persistent while renaming! The rename button uses the buffer's
+   * pointer to identify itself over redraws. */
+  rename_buffer_ = std::move(old_view.rename_buffer_);
+  old_view.rename_buffer_ = nullptr;
+
   update_children_from_old_recursive(*this, old_view);
 
   /* Finished (re-)constructing the tree. */
@@ -153,6 +167,95 @@ void AbstractTreeView::change_state_delayed()
 
 /* ---------------------------------------------------------------------- */
 
+void AbstractTreeViewItem::tree_row_click_fn(struct bContext * /*C*/,
+                                             void *but_arg1,
+                                             void * /*arg2*/)
+{
+  uiButTreeRow *tree_row_but = (uiButTreeRow *)but_arg1;
+  BasicTreeViewItem &tree_item = reinterpret_cast<BasicTreeViewItem &>(*tree_row_but->tree_item);
+
+  /* Let a click on an opened item activate it, a second click will close it then.
+   * TODO Should this be for asset catalogs only? */
+  if (tree_item.is_collapsed() || tree_item.is_active()) {
+    tree_item.toggle_collapsed();
+  }
+  tree_item.activate();
+}
+
+void AbstractTreeViewItem::add_treerow_button(uiBlock &block)
+{
+  tree_row_but_ = (uiButTreeRow *)uiDefBut(
+      &block, UI_BTYPE_TREEROW, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, nullptr, 0, 0, 0, 0, "");
+
+  tree_row_but_->tree_item = reinterpret_cast<uiTreeViewItemHandle *>(this);
+  UI_but_func_set(&tree_row_but_->but, tree_row_click_fn, tree_row_but_, nullptr);
+  UI_but_treerow_indentation_set(&tree_row_but_->but, count_parents());
+}
+
+AbstractTreeViewItem *AbstractTreeViewItem::find_tree_item_from_rename_button(
+    const uiBut &rename_but)
+{
+  /* A minimal sanity check, can't do much more here. */
+  BLI_assert(rename_but.type == UI_BTYPE_TEXT && rename_but.poin);
+
+  LISTBASE_FOREACH (uiBut *, but, &rename_but.block->buttons) {
+    if (but->type != UI_BTYPE_TREEROW) {
+      continue;
+    }
+
+    uiButTreeRow *tree_row_but = (uiButTreeRow *)but;
+    AbstractTreeViewItem *item = reinterpret_cast<AbstractTreeViewItem *>(tree_row_but->tree_item);
+    const AbstractTreeView &tree_view = item->get_tree_view();
+
+    if (item->is_renaming() && (t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list