[Bf-blender-cvs] [400d7235c3a] asset-browser-grid-view: Mouse hover highlight for grid items

Julian Eisel noreply at git.blender.org
Wed Feb 9 18:05:24 CET 2022


Commit: 400d7235c3a50669c8d1b0ed6c22f14a3dde10ea
Author: Julian Eisel
Date:   Wed Feb 9 14:41:11 2022 +0100
Branches: asset-browser-grid-view
https://developer.blender.org/rB400d7235c3a50669c8d1b0ed6c22f14a3dde10ea

Mouse hover highlight for grid items

Like the tree-view rows, grid items use an overlapping layout to draw
the background and a custom layout on top. There is a new dedicated
button type for the grid view items.
Adds some related bits needed for persistent view-item state storage.
Also a bunch of code for the grid item button type can be shared with
the tree-row one, but I prefer doing that separately.

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

M	source/blender/editors/include/UI_grid_view.hh
M	source/blender/editors/include/UI_interface.h
M	source/blender/editors/include/UI_tree_view.hh
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_query.c
M	source/blender/editors/interface/interface_widgets.c

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

diff --git a/source/blender/editors/include/UI_grid_view.hh b/source/blender/editors/include/UI_grid_view.hh
index 99aff838593..4c39f2f00ba 100644
--- a/source/blender/editors/include/UI_grid_view.hh
+++ b/source/blender/editors/include/UI_grid_view.hh
@@ -27,8 +27,10 @@
 #include "BLI_vector.hh"
 #include "UI_resources.h"
 
+struct bContext;
 struct PreviewImage;
 struct uiBlock;
+struct uiButGridTile;
 struct uiLayout;
 struct wmNotifier;
 
@@ -41,10 +43,17 @@ class AbstractGridView;
  * \{ */
 
 class AbstractGridViewItem {
-  friend AbstractGridView;
+  friend class AbstractGridView;
+  friend class GridViewLayoutBuilder;
 
   const AbstractGridView *view_;
 
+ protected:
+  /** This label is used as the default way to identifying an item in the view. */
+  std::string label_{};
+  /** Every visible item gets a button of type #UI_BTYPE_GRID_TILE during the layout building. */
+  uiButGridTile *grid_tile_but_ = nullptr;
+
  public:
   virtual ~AbstractGridViewItem() = default;
 
@@ -52,8 +61,20 @@ class AbstractGridViewItem {
 
   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,
+   * renaming, etc.). By default this just matches the item's label. If that isn't good enough for
+   * a sub-class, that can override it.
+   */
+  virtual bool matches(const AbstractGridViewItem &other) const;
+
  protected:
   AbstractGridViewItem() = default;
+
+ private:
+  static void grid_tile_click_fn(bContext *, void *but_arg1, void *);
+  void add_grid_tile_button(uiBlock &block);
 };
 
 /** \} */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 607df5df934..b6c274401a2 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -94,6 +94,8 @@ typedef struct uiTreeViewHandle uiTreeViewHandle;
 typedef struct uiTreeViewItemHandle uiTreeViewItemHandle;
 /* C handle for C++ #ui::AbstractGridView type. */
 typedef struct uiGridViewHandle uiGridViewHandle;
+/* C handle for C++ #ui::AbstractGridViewItem type. */
+typedef struct uiGridViewItemHandle uiGridViewItemHandle;
 
 /* Defines */
 
@@ -407,6 +409,8 @@ typedef enum {
   UI_BTYPE_DECORATOR = 58 << 9,
   /* An item in a tree view. Parent items may be collapsible. */
   UI_BTYPE_TREEROW = 59 << 9,
+  /* An item in a grid view. */
+  UI_BTYPE_GRID_TILE = 60 << 9,
 } eButType;
 
 #define BUTTYPE (63 << 9)
@@ -3178,6 +3182,7 @@ void UI_block_views_listen(const uiBlock *block,
                            const struct wmRegionListenerParams *listener_params);
 
 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);
 /**
  * Attempt to start dragging the tree-item \a item_. This will not work if the tree item doesn't
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index 7002754b934..47c99d3e12b 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -203,7 +203,7 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
   bool is_renaming_ = false;
 
  protected:
-  /** This label is used for identifying an item within its parent. */
+  /** This label is used as the default way to identifying an item within its parent. */
   std::string label_{};
   /** Every visible item gets a button of type #UI_BTYPE_TREEROW during the layout building. */
   uiButTreeRow *tree_row_but_ = nullptr;
diff --git a/source/blender/editors/interface/grid_view.cc b/source/blender/editors/interface/grid_view.cc
index ae7f527f817..4994aad267c 100644
--- a/source/blender/editors/interface/grid_view.cc
+++ b/source/blender/editors/interface/grid_view.cc
@@ -68,6 +68,44 @@ GridViewStyle::GridViewStyle(int width, int height) : tile_width(width), tile_he
 
 /* ---------------------------------------------------------------------- */
 
+bool AbstractGridViewItem::matches(const AbstractGridViewItem &other) const
+{
+  return label_ == other.label_;
+}
+
+void AbstractGridViewItem::grid_tile_click_fn(struct bContext * /*C*/,
+                                              void *but_arg1,
+                                              void * /*arg2*/)
+{
+  uiButGridTile *grid_tile_but = (uiButGridTile *)but_arg1;
+  AbstractGridViewItem &grid_item = reinterpret_cast<AbstractGridViewItem &>(
+      *grid_tile_but->view_item);
+
+  //  tree_item.activate();
+}
+
+void AbstractGridViewItem::add_grid_tile_button(uiBlock &block)
+{
+  const GridViewStyle &style = get_view().get_style();
+  grid_tile_but_ = (uiButGridTile *)uiDefBut(&block,
+                                             UI_BTYPE_GRID_TILE,
+                                             0,
+                                             "",
+                                             0,
+                                             0,
+                                             style.tile_width,
+                                             style.tile_height,
+                                             nullptr,
+                                             0,
+                                             0,
+                                             0,
+                                             0,
+                                             "");
+
+  grid_tile_but_->view_item = reinterpret_cast<uiGridViewItemHandle *>(this);
+  UI_but_func_set(&grid_tile_but_->but, grid_tile_click_fn, grid_tile_but_, nullptr);
+}
+
 const AbstractGridView &AbstractGridViewItem::get_view() const
 {
   if (UNLIKELY(!view_)) {
@@ -87,7 +125,9 @@ class GridViewLayoutBuilder {
  public:
   GridViewLayoutBuilder(uiBlock &block);
 
-  void build_from_view(const AbstractGridView &grid_view);
+  void build_from_view(const AbstractGridView &grid_view) const;
+  void build_grid_tile(uiLayout &grid_layout, AbstractGridViewItem &item) const;
+
   uiLayout *current_layout() const;
 };
 
@@ -95,8 +135,19 @@ GridViewLayoutBuilder::GridViewLayoutBuilder(uiBlock &block) : block_(block)
 {
 }
 
-void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view)
+void GridViewLayoutBuilder::build_grid_tile(uiLayout &grid_layout,
+                                            AbstractGridViewItem &item) const
 {
+  uiLayout *overlap = uiLayoutOverlap(&grid_layout);
+
+  item.add_grid_tile_button(block_);
+  item.build_grid_tile(*uiLayoutRow(overlap, false));
+}
+
+void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view) const
+{
+  uiLayout *prev_layout = current_layout();
+
   uiLayout &layout = *uiLayoutColumn(current_layout(), false);
   const GridViewStyle &style = grid_view.get_style();
 
@@ -108,7 +159,7 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view)
 
   int item_count = 0;
   grid_view.foreach_item([&](AbstractGridViewItem &item) {
-    item.build_grid_tile(*grid_layout);
+    build_grid_tile(*grid_layout, item);
     item_count++;
   });
 
@@ -120,6 +171,8 @@ void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view)
       uiItemS(grid_layout);
     }
   }
+
+  UI_block_layout_set_current(&block_, prev_layout);
 }
 
 uiLayout *GridViewLayoutBuilder::current_layout() const
@@ -183,6 +236,9 @@ void PreviewGridItem::build_grid_tile(uiLayout &layout) const
 using namespace blender::ui;
 
 /* ---------------------------------------------------------------------- */
+/* C-API */
+
+using namespace blender::ui;
 
 bool UI_grid_view_listen_should_redraw(const uiGridViewHandle *view_handle,
                                        const wmNotifier *notifier)
@@ -190,3 +246,11 @@ bool UI_grid_view_listen_should_redraw(const uiGridViewHandle *view_handle,
   const AbstractGridView &view = *reinterpret_cast<const AbstractGridView *>(view_handle);
   return view.listen(*notifier);
 }
+
+bool UI_grid_view_item_matches(const uiGridViewItemHandle *a_handle,
+                               const uiGridViewItemHandle *b_handle)
+{
+  const AbstractGridViewItem &a = reinterpret_cast<const AbstractGridViewItem &>(*a_handle);
+  const AbstractGridViewItem &b = reinterpret_cast<const AbstractGridViewItem &>(*b_handle);
+  return a.matches(b);
+}
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 3cbea922bed..4838bb1fa8c 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -781,6 +781,15 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
     }
   }
 
+  if ((but->type == UI_BTYPE_GRID_TILE) && (oldbut->type == UI_BTYPE_GRID_TILE)) {
+    uiButGridTile *but_gridtile = (uiButGridTile *)but;
+    uiButGridTile *oldbut_gridtile = (uiButGridTile *)oldbut;
+    if (!but_gridtile->view_item || !oldbut_gridtile->view_item ||
+        !UI_grid_view_item_matches(but_gridtile->view_item, oldbut_gridtile->view_item)) {
+      return false;
+    }
+  }
+
   return true;
 }
 
@@ -907,6 +916,12 @@ static void ui_but_update_old_active_from_new(uiBut *oldbut, uiBut *but)
       SWAP(uiTreeViewItemHandle *, treerow_newbut->tree_item, treerow_oldbut->tree_item);
       break;
     }
+    case UI_BTYPE_GRID_TILE: {
+      uiButGridTile *gridtile_oldbut = (uiButGridTile *)oldbut;
+      uiButGridTile *gridtile_newbut = (uiButGridTile *)but;
+      SWAP(uiGridViewItemHandle *, gridtile_newbut->view_item, gridtile_oldbut->view_item);
+      break;
+    }
     default:
       break;
   }
@@ -996,9 +1011,9 @@ static bool ui_but_update_from_old_block(const bContext *C,
   else {
     int flag_copy = UI_BUT_DRAG_MULTI;
 
-    /* Stupid special case: The active button may be inside (as in, overlapped on top) a tree-row
+    /* Stupid special case: The active button may be inside (as in, overlapped on top) a view-item
      * button which we also want to keep highlighted then. */
-    if (but->type == UI_BTYPE_TREEROW

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list