[Bf-blender-cvs] [696295f8494] asset-browser-grid-view: Support active item

Julian Eisel noreply at git.blender.org
Mon Feb 14 17:57:11 CET 2022


Commit: 696295f84944da8e830c757a8c00126723024c5b
Author: Julian Eisel
Date:   Mon Feb 14 17:48:51 2022 +0100
Branches: asset-browser-grid-view
https://developer.blender.org/rB696295f84944da8e830c757a8c00126723024c5b

Support active item

Makes activating assets in the Asset Browser work. The active item is only
stored at the UI level now, so it's not stored in files, not accessible via
context and is lost when changing editors. The Asset Browser itself will have
to get a way to store that.

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

M	source/blender/editors/include/UI_grid_view.hh
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/interface/grid_view.cc
M	source/blender/editors/interface/interface.c
M	source/blender/editors/interface/interface_handlers.c
M	source/blender/editors/interface/interface_intern.h
M	source/blender/editors/interface/interface_view.cc
M	source/blender/editors/interface/tree_view.cc

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

diff --git a/source/blender/editors/include/UI_grid_view.hh b/source/blender/editors/include/UI_grid_view.hh
index fc0de424ef0..e00dabd4cda 100644
--- a/source/blender/editors/include/UI_grid_view.hh
+++ b/source/blender/editors/include/UI_grid_view.hh
@@ -49,6 +49,8 @@ class AbstractGridViewItem {
 
   const AbstractGridView *view_;
 
+  bool is_active_ = false;
+
  protected:
   /** This label is used as the default way to identifying an item in the view. */
   std::string label_{};
@@ -60,8 +62,6 @@ class AbstractGridViewItem {
 
   virtual void build_grid_tile(uiLayout &layout) const = 0;
 
-  const AbstractGridView &get_view() const;
-
   /**
    * Compare this item to \a other to check if they represent the same data.
    * Used to recognize an item from a previous redraw, to be able to keep its state (e.g. active,
@@ -70,9 +70,36 @@ class AbstractGridViewItem {
    */
   virtual bool matches(const AbstractGridViewItem &other) const;
 
+  const AbstractGridView &get_view() const;
+
+  /**
+   * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
+   * can't be sure about the item state.
+   */
+  bool is_active() const;
+
  protected:
   AbstractGridViewItem() = default;
 
+  /** Called when the item's state changes from inactive to active. */
+  virtual void on_activate();
+
+  /**
+   * Copy persistent state (e.g. active, selection, etc.) from a matching item of
+   * the last redraw to this item. If sub-classes introduce more advanced state they should
+   * override this and make it update their state accordingly.
+   */
+  virtual void update_from_old(const AbstractGridViewItem &old);
+
+  /**
+   * Activates this item, deactivates other items, and calls the
+   * #AbstractGridViewItem::on_activate() function.
+   * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise the
+   * actual item state is unknown, possibly calling state-change update functions incorrectly.
+   */
+  void activate();
+  void deactivate();
+
  private:
   static void grid_tile_click_fn(bContext *, void *but_arg1, void *);
   void add_grid_tile_button(uiBlock &block);
@@ -91,12 +118,14 @@ struct GridViewStyle {
 };
 
 class AbstractGridView {
+  friend class AbstractGridViewItem;
   friend class GridViewBuilder;
   friend class GridViewLayoutBuilder;
 
  protected:
   Vector<std::unique_ptr<AbstractGridViewItem>> items_;
   GridViewStyle style_;
+  bool is_reconstructed_ = false;
 
  public:
   AbstractGridView();
@@ -128,7 +157,22 @@ class AbstractGridView {
  protected:
   virtual void build_items() = 0;
 
+  /**
+   * Check if the view is fully (re-)constructed. That means, both #build_items() and
+   * #update_from_old() have finished.
+   */
+  bool is_reconstructed() const;
+
  private:
+  /**
+   * Match the grid-view against an earlier version of itself (if any) and copy the old UI state
+   * (e.g. active, selected, renaming, etc.) to the new one. See
+   * #AbstractGridViewItem.update_from_old().
+   */
+  void update_from_old(uiBlock &new_block);
+  AbstractGridViewItem *find_matching_item(const AbstractGridViewItem &lookup_item,
+                                           const AbstractGridView &view) const;
+
   /**
    * Add an already constructed item, moving ownership to the grid-view.
    * All items must be added through this, it handles important invariants!
@@ -169,7 +213,6 @@ class GridViewBuilder {
  */
 class PreviewGridItem : public AbstractGridViewItem {
  public:
-  std::string label{};
   int preview_icon_id = ICON_NONE;
 
   PreviewGridItem(StringRef label, int preview_icon_id);
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index cf8233d565d..a32774eb717 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -3165,6 +3165,7 @@ void UI_interface_tag_script_reload(void);
 void UI_block_views_listen(const uiBlock *block,
                            const struct wmRegionListenerParams *listener_params);
 
+bool UI_grid_view_item_is_active(const uiGridViewItemHandle *item_handle);
 bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item);
 bool UI_grid_view_item_matches(const uiGridViewItemHandle *a, const uiGridViewItemHandle *b);
 bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a, const uiTreeViewItemHandle *b);
diff --git a/source/blender/editors/interface/grid_view.cc b/source/blender/editors/interface/grid_view.cc
index 85c3a32c10f..c904239416a 100644
--- a/source/blender/editors/interface/grid_view.cc
+++ b/source/blender/editors/interface/grid_view.cc
@@ -60,6 +60,49 @@ bool AbstractGridView::listen(const wmNotifier &) const
   return false;
 }
 
+AbstractGridViewItem *AbstractGridView::find_matching_item(const AbstractGridViewItem &lookup_item,
+                                                           const AbstractGridView &view) const
+{
+  for (const auto &iter_item_ptr : view.items_) {
+    if (lookup_item.matches(*iter_item_ptr)) {
+      /* We have a matching item! */
+      return iter_item_ptr.get();
+    }
+  }
+
+  return nullptr;
+}
+
+void AbstractGridView::update_from_old(uiBlock &new_block)
+{
+  uiGridViewHandle *old_view_handle = ui_block_grid_view_find_matching_in_old_block(
+      &new_block, reinterpret_cast<uiGridViewHandle *>(this));
+  if (!old_view_handle) {
+    /* Initial construction, nothing to update. */
+    is_reconstructed_ = true;
+    return;
+  }
+
+  AbstractGridView &old_view = reinterpret_cast<AbstractGridView &>(*old_view_handle);
+
+  foreach_item([this, &old_view](AbstractGridViewItem &new_item) {
+    const AbstractGridViewItem *matching_old_item = find_matching_item(new_item, old_view);
+    if (!matching_old_item) {
+      return;
+    }
+
+    new_item.update_from_old(*matching_old_item);
+  });
+
+  /* Finished (re-)constructing the tree. */
+  is_reconstructed_ = true;
+}
+
+bool AbstractGridView::is_reconstructed() const
+{
+  return is_reconstructed_;
+}
+
 const GridViewStyle &AbstractGridView::get_style() const
 {
   return style_;
@@ -89,7 +132,7 @@ void AbstractGridViewItem::grid_tile_click_fn(struct bContext * /*C*/,
   AbstractGridViewItem &grid_item = reinterpret_cast<AbstractGridViewItem &>(
       *grid_tile_but->view_item);
 
-  //  tree_item.activate();
+  grid_item.activate();
 }
 
 void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
@@ -114,6 +157,45 @@ void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
   UI_but_func_set(&grid_tile_but_->but, grid_tile_click_fn, grid_tile_but_, nullptr);
 }
 
+bool AbstractGridViewItem::is_active() const
+{
+  BLI_assert_msg(get_view().is_reconstructed(),
+                 "State can't be queried until reconstruction is completed");
+  return is_active_;
+}
+
+void AbstractGridViewItem::on_activate()
+{
+  /* Do nothing by default. */
+}
+
+void AbstractGridViewItem::update_from_old(const AbstractGridViewItem &old)
+{
+  is_active_ = old.is_active_;
+}
+
+void AbstractGridViewItem::activate()
+{
+  BLI_assert_msg(get_view().is_reconstructed(),
+                 "Item activation can't be done until reconstruction is completed");
+
+  if (is_active()) {
+    return;
+  }
+
+  /* Deactivate other items in the tree. */
+  get_view().foreach_item([](auto &item) { item.deactivate(); });
+
+  on_activate();
+
+  is_active_ = true;
+}
+
+void AbstractGridViewItem::deactivate()
+{
+  is_active_ = false;
+}
+
 const AbstractGridView &AbstractGridViewItem::get_view() const
 {
   if (UNLIKELY(!view_)) {
@@ -337,6 +419,7 @@ GridViewBuilder::GridViewBuilder(uiBlock &block) : block_(block)
 void GridViewBuilder::build_grid_view(AbstractGridView &grid_view, const View2D &v2d)
 {
   grid_view.build_items();
+  grid_view.update_from_old(block_);
 
   GridViewLayoutBuilder builder(block_);
   builder.build_from_view(grid_view, v2d);
@@ -350,8 +433,9 @@ void GridViewBuilder::build_grid_view(AbstractGridView &grid_view, const View2D
 /* ---------------------------------------------------------------------- */
 
 PreviewGridItem::PreviewGridItem(StringRef label, int preview_icon_id)
-    : label(label), preview_icon_id(preview_icon_id)
+    : preview_icon_id(preview_icon_id)
 {
+  label_ = label;
 }
 
 void PreviewGridItem::build_grid_tile(uiLayout &layout) const
@@ -362,7 +446,7 @@ void PreviewGridItem::build_grid_tile(uiLayout &layout) const
                                 UI_BTYPE_PREVIEW_TILE,
                                 0,
                                 preview_icon_id,
-                                label.c_str(),
+                                label_.c_str(),
                                 0,
                                 0,
                                 style.tile_width,
@@ -388,6 +472,12 @@ using namespace blender::ui;
 
 using namespace blender::ui;
 
+bool UI_grid_view_item_is_active(const uiGridViewItemHandle *item_handle)
+{
+  const AbstractGridViewItem &item = reinterpret_cast<const AbstractGridViewItem &>(*item_handle);
+  return item.is_active();
+}
+
 bool UI_grid_view_listen_should_redraw(const uiGridViewHandle *view_handle,
                                        const wmNotifier *notifier)
 {
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index fcbc208a881..a1a02b6c019 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -2229,6 +2229,15 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
         }
         break;
       }
+      case UI_BTYPE_GRID_TILE: {
+        uiButGridTile *grid_tile_but = (uiButGridTile *)but;
+
+        is_push = -1;
+        if (grid_tile_but->view_item) {
+          is_push = UI_grid_view_item_is_active(grid_tile_but->view_item);
+        }
+        break;
+      }
       default:
         is_push = -1;
         break;
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 2c76ea7aced..69b87f24c99 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -4855,7 +4855,6 @@ static int ui_do_but_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list