[Bf-blender-cvs] [925b82efb02] asset-browser-grid-view: Basic grid layout with big preview tiles
Julian Eisel
noreply at git.blender.org
Fri Feb 4 15:21:45 CET 2022
Commit: 925b82efb02373f34ce577167c69be1b3dd72055
Author: Julian Eisel
Date: Fri Feb 4 15:18:40 2022 +0100
Branches: asset-browser-grid-view
https://developer.blender.org/rB925b82efb02373f34ce577167c69be1b3dd72055
Basic grid layout with big preview tiles
Draws the asset previews in a grid layout, similar to the "old" Asset
Browser. No interactivity is supported yet.
The layout is managed through the grid-view.
===================================================================
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_template_asset_view.cc
M source/blender/editors/interface/interface_template_list.cc
M source/blender/editors/space_assets/asset_browser_draw.cc
M source/blender/editors/space_assets/asset_view.cc
M source/blender/editors/space_assets/asset_view.hh
M source/blender/editors/space_file/filesel.c
===================================================================
diff --git a/source/blender/editors/include/UI_grid_view.hh b/source/blender/editors/include/UI_grid_view.hh
index 945c9444db7..99aff838593 100644
--- a/source/blender/editors/include/UI_grid_view.hh
+++ b/source/blender/editors/include/UI_grid_view.hh
@@ -23,27 +23,145 @@
#pragma once
+#include "BLI_function_ref.hh"
+#include "BLI_vector.hh"
+#include "UI_resources.h"
+
+struct PreviewImage;
+struct uiBlock;
+struct uiLayout;
struct wmNotifier;
namespace blender::ui {
+class AbstractGridView;
+
+/* ---------------------------------------------------------------------- */
+/** \name Grid-View Item Type
+ * \{ */
+
class AbstractGridViewItem {
+ friend AbstractGridView;
+
+ const AbstractGridView *view_;
+
public:
virtual ~AbstractGridViewItem() = default;
+ virtual void build_grid_tile(uiLayout &layout) const = 0;
+
+ const AbstractGridView &get_view() const;
+
protected:
AbstractGridViewItem() = default;
};
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Grid-View Base Class
+ * \{ */
+
+struct GridViewStyle {
+ GridViewStyle(int width, int height);
+ int tile_width = 0;
+ int tile_height = 0;
+};
+
class AbstractGridView {
+ friend class GridViewBuilder;
+ friend class GridViewLayoutBuilder;
+
+ protected:
+ Vector<std::unique_ptr<AbstractGridViewItem>> items_;
+ GridViewStyle style_;
+
public:
+ AbstractGridView();
virtual ~AbstractGridView() = default;
+ using ItemIterFn = FunctionRef<void(AbstractGridViewItem &)>;
+ void foreach_item(ItemIterFn iter_fn) const;
+
/** Listen to a notifier, returning true if a redraw is needed. */
virtual bool listen(const wmNotifier &) const;
- // protected:
- virtual void build() = 0;
+ /**
+ * Convenience wrapper constructing the item by forwarding given arguments to the constructor of
+ * the type (\a ItemT).
+ *
+ * E.g. if your grid-item type has the following constructor:
+ * \code{.cpp}
+ * MyGridItem(std::string str, int i);
+ * \endcode
+ * You can add an item like this:
+ * \code
+ * add_item<MyGridItem>("blabla", 42);
+ * \endcode
+ */
+ template<class ItemT, typename... Args> inline ItemT &add_item(Args &&...args);
+ const GridViewStyle &get_style() const;
+
+ protected:
+ virtual void build_items() = 0;
+
+ private:
+ /**
+ * Add an already constructed item, moving ownership to the grid-view.
+ * All items must be added through this, it handles important invariants!
+ */
+ AbstractGridViewItem &add_item(std::unique_ptr<AbstractGridViewItem> item);
};
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Grid-View Builder
+ *
+ * TODO unify this with `TreeViewBuilder` and call view-specific functions via type erased view?
+ * \{ */
+
+class GridViewBuilder {
+ uiBlock &block_;
+
+ public:
+ GridViewBuilder(uiBlock &block);
+
+ void build_grid_view(AbstractGridView &grid_view);
+};
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Predefined Grid-View Item Types
+ *
+ * Common, Basic Grid-View Item Types.
+ * \{ */
+
+/**
+ * A grid item that shows preview image icons at a nicely readable size (multiple of the normal UI
+ * unit size).
+ */
+class PreviewGridItem : public AbstractGridViewItem {
+ public:
+ std::string label{};
+ int preview_icon_id = ICON_NONE;
+
+ PreviewGridItem(StringRef label, int preview_icon_id);
+
+ void build_grid_tile(uiLayout &layout) const override;
+};
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+
+template<class ItemT, typename... Args> inline ItemT &AbstractGridView::add_item(Args &&...args)
+{
+ static_assert(std::is_base_of<AbstractGridViewItem, ItemT>::value,
+ "Type must derive from and implement the AbstractGridViewItem interface");
+
+ return dynamic_cast<ItemT &>(add_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
+}
+
} // namespace blender::ui
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index cdc7eb25b4c..e5ef3bb2806 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1788,6 +1788,14 @@ AutoComplete *UI_autocomplete_begin(const char *startname, size_t maxlen);
void UI_autocomplete_update_name(AutoComplete *autocpl, const char *name);
int UI_autocomplete_end(AutoComplete *autocpl, char *autoname);
+/**
+ * A decent size for a button (typically #UI_BTYPE_PREVIEW_TILE) to display a nicely readable
+ * preview with label in.
+ */
+int UI_preview_tile_size_x(void);
+int UI_preview_tile_size_y(void);
+int UI_preview_tile_size_y_no_label(void);
+
/* Panels
*
* Functions for creating, freeing and drawing panels. The API here
diff --git a/source/blender/editors/interface/grid_view.cc b/source/blender/editors/interface/grid_view.cc
index 5315bd1447e..72614319bf9 100644
--- a/source/blender/editors/interface/grid_view.cc
+++ b/source/blender/editors/interface/grid_view.cc
@@ -18,9 +18,12 @@
* \ingroup edinterface
*/
+#include <stdexcept>
+
#include "WM_types.h"
#include "UI_interface.h"
+#include "interface_intern.h"
#include "UI_grid_view.hh"
@@ -28,12 +31,137 @@ namespace blender::ui {
/* ---------------------------------------------------------------------- */
+AbstractGridView::AbstractGridView() : style_(UI_preview_tile_size_x(), UI_preview_tile_size_y())
+{
+}
+
+AbstractGridViewItem &AbstractGridView::add_item(std::unique_ptr<AbstractGridViewItem> item)
+{
+ items_.append(std::move(item));
+
+ AbstractGridViewItem &added_item = *items_.last();
+ added_item.view_ = this;
+ return added_item;
+}
+
+void AbstractGridView::foreach_item(ItemIterFn iter_fn) const
+{
+ for (auto &item_ptr : items_) {
+ iter_fn(*item_ptr);
+ }
+}
+
bool AbstractGridView::listen(const wmNotifier &) const
{
/* Nothing by default. */
return false;
}
+const GridViewStyle &AbstractGridView::get_style() const
+{
+ return style_;
+}
+
+GridViewStyle::GridViewStyle(int width, int height) : tile_width(width), tile_height(height)
+{
+}
+
+/* ---------------------------------------------------------------------- */
+
+const AbstractGridView &AbstractGridViewItem::get_view() const
+{
+ if (UNLIKELY(!view_)) {
+ throw std::runtime_error(
+ "Invalid state, item must be added through AbstractGridView::add_item()");
+ }
+ return *view_;
+}
+
+/* ---------------------------------------------------------------------- */
+
+class GridViewLayoutBuilder {
+ uiBlock &block_;
+
+ friend GridViewBuilder;
+
+ public:
+ GridViewLayoutBuilder(uiBlock &block);
+
+ void build_from_view(const AbstractGridView &grid_view);
+ uiLayout *current_layout() const;
+};
+
+GridViewLayoutBuilder::GridViewLayoutBuilder(uiBlock &block) : block_(block)
+{
+}
+
+void GridViewLayoutBuilder::build_from_view(const AbstractGridView &grid_view)
+{
+ uiLayout &layout = *uiLayoutColumn(current_layout(), false);
+ const GridViewStyle &style = grid_view.get_style();
+
+ const int cols_per_row = uiLayoutGetWidth(&layout) / style.tile_width;
+ uiLayout *grid_layout = uiLayoutGridFlow(&layout, true, cols_per_row, true, true, true);
+
+ grid_view.foreach_item([&](AbstractGridViewItem &item) { item.build_grid_tile(*grid_layout); });
+}
+
+uiLayout *GridViewLayoutBuilder::current_layout() const
+{
+ return block_.curlayout;
+}
+
+/* ---------------------------------------------------------------------- */
+
+GridViewBuilder::GridViewBuilder(uiBlock &block) : block_(block)
+{
+}
+
+void GridViewBuilder::build_grid_view(AbstractGridView &grid_view)
+{
+ grid_view.build_items();
+
+ GridViewLayoutBuilder builder(block_);
+ builder.build_from_view(grid_view);
+ // grid_view.update_from_old(block_);
+ // grid_view.change_state_delayed();
+
+ // TreeViewLayoutBuilder builder(block_);
+ // builder.build_from_tree(tree_view);
+}
+
+/* ---------------------------------------------------------------------- */
+
+PreviewGridItem::PreviewGridItem(StringRef label, int preview_icon_id)
+ : label(label), preview_icon_id(preview_icon_id)
+{
+}
+
+void PreviewGridItem::build_grid_tile(uiLayout &layout) const
+{
+ const GridViewStyle &style = get_view().get_style();
+ uiBlock *block = uiLayoutGetBlock(&layout);
+ uiBut *but = uiDefIconTextBut(block,
+ UI_BTYPE_PREVIEW_TILE,
+ 0,
+ preview_icon_id,
+ label.c_str(),
+ 0,
+ 0,
+ style.tile_width,
+ style.tile_height,
+ nullptr,
+ 0,
+ 0,
+ 0,
+ 0,
+ "");
+ ui_def_but_icon(but,
+ preview_icon_id,
+ /* NOLINTNEXTLINE: bugprone-suspicious-enum-usage */
+ UI_HAS_ICON | UI_BUT_ICON_PREVIEW);
+}
+
} // namespace blender::ui
using namespace blender::ui;
diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c
index 2292bf759b7..3cbea922bed 100644
--- a/source/blender/editors/interface/interface.c
+++ b/source/blender/editors/interface/interface.c
@@ -4910,6 +4910,21 @@ int UI_autocomplete_end(AutoComplete *autocpl, char *autoname)
return match;
}
+int UI_preview_tile_size_x(void)
+{
+ return round_fl_to_int((96.0f / 20.0f) * UI_UNIT_X);
+}
+
+int UI_preview_tile_size_y(void)
+{
+ return round_fl_to_int((96.0f / 20.0f) * UI_UNIT_Y);
+}
+
+int UI_preview_tile_size_y_no_label(void)
+{
+ return round_fl_to_int((96.0f / 20.0f) * UI_UNIT_Y - UI_UNIT_Y);
+}
+
static void ui_but_update_and_icon_set(uiBut *but, int icon)
{
if (icon) {
diff --git a/source/blender/editors/interface/interface_template_asset_view.cc b/source/blender/editors/interface/interface_template_asset_view.cc
index 0a3cff5fa98..2a26ff96105 100644
--- a/source/blender/e
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list