40 items_.append(std::move(item));
49void AbstractGridView::foreach_view_item(
FunctionRef<
void(AbstractViewItem &)> iter_fn)
const
53 for (
const auto &item_ptr :
items_) {
60 for (
const auto &item_ptr :
items_) {
67 for (
const auto &item_ptr :
items_) {
68 if (item_ptr->is_filtered_visible()) {
81 return match ? *match :
nullptr;
84void AbstractGridView::update_children_from_old(
const AbstractView &old_view)
90 if (!matching_old_item) {
94 new_item.update_from_old(*matching_old_item);
124 style_.tile_width = tile_width;
125 style_.tile_height = tile_height;
140void AbstractGridViewItem::grid_tile_click_fn(
bContext *
C,
void *but_arg1,
void * )
149void AbstractGridViewItem::add_grid_tile_button(
uiBlock &block)
177 throw std::runtime_error(
178 "Invalid state, item must be added through AbstractGridView::add_item()");
218 const int cols_per_row_ = 0;
221 std::optional<IndexRange> visible_items_range_;
236 void add_spacer_button(
uiBlock &block,
int row_count)
const;
242 const int cols_per_row,
244 : grid_view_(grid_view), style_(grid_view.get_style()), cols_per_row_(cols_per_row)
247 visible_items_range_ = this->get_visible_range(v2d, force_visible_item);
256 std::optional<int> index;
260 if (&item == &iter_item) {
269IndexRange BuildOnlyVisibleButtonsHelper::get_visible_range(
270 const View2D &v2d,
const AbstractGridViewItem *force_visible_item)
const
274 int first_idx_in_view = 0;
277 if (!
IS_EQF(scroll_ofs_y, 0)) {
278 const int scrolled_away_rows = int(scroll_ofs_y) / style_.
tile_height;
280 first_idx_in_view = scrolled_away_rows * cols_per_row_;
284 const int count_rows_in_view = std::max(view_height / style_.
tile_height, 1);
285 const int max_items_in_view = (count_rows_in_view + 1) * cols_per_row_;
288 IndexRange visible_items(first_idx_in_view, max_items_in_view);
291 if (force_visible_item && force_visible_item->is_filtered_visible()) {
293 if (!visible_items.contains(*item_idx)) {
295 return IndexRange((item_idx == 0) ? 0 : *item_idx % cols_per_row_, max_items_in_view);
300 return visible_items;
305 return !visible_items_range_ || visible_items_range_->contains(item_idx);
310 if (!visible_items_range_ || visible_items_range_->is_empty()) {
313 const int first_idx_in_view = visible_items_range_->first();
314 if (first_idx_in_view < 1) {
317 const int tot_tiles_before_visible = first_idx_in_view;
318 const int scrolled_away_rows = tot_tiles_before_visible / cols_per_row_;
319 this->add_spacer_button(block, scrolled_away_rows);
324 if (!visible_items_range_ || visible_items_range_->is_empty()) {
327 const int last_item_idx = grid_view_.get_item_count_filtered() - 1;
328 const int last_visible_idx = visible_items_range_->last();
330 if (last_item_idx > last_visible_idx) {
331 const int remaining_rows = (cols_per_row_ > 0) ?
ceilf((last_item_idx - last_visible_idx) /
332 float(cols_per_row_)) :
334 BuildOnlyVisibleButtonsHelper::add_spacer_button(block, remaining_rows);
338void BuildOnlyVisibleButtonsHelper::add_spacer_button(
uiBlock &block,
const int row_count)
const
342 for (
int remaining_rows = row_count; remaining_rows > 0;) {
343 const short row_count_this_iter = std::min(
344 std::numeric_limits<short>::max() / style_.
tile_height, remaining_rows);
358 remaining_rows -= row_count_this_iter;
386void GridViewLayoutBuilder::build_grid_tile(
const bContext &
C,
393 item.add_grid_tile_button(block_);
401 uiLayout *parent_layout = this->current_layout();
412 const int cols_per_row = std::max(guessed_layout_width / style.
tile_width, 1);
418 v2d, grid_view, cols_per_row, search_highlight_item);
432 if ((item_idx % cols_per_row) == 0) {
433 row = &layout.
row(
true);
436 this->build_grid_tile(
C, *row, item);
445uiLayout *GridViewLayoutBuilder::current_layout()
const
457 std::optional<StringRef> search_string)
467 grid_view.
filter(search_string);
484 BIFIconID override_preview_icon_id)
const
534void PreviewGridItem::on_activate(
bContext &
C)
ARegion * CTX_wm_region_popup(const bContext *C)
ARegion * CTX_wm_region(const bContext *C)
BLI_INLINE int BLI_rcti_size_y(const struct rcti *rct)
void UI_but_func_set(uiBut *but, std::function< void(bContext &)> func)
uiBut * uiDefBut(uiBlock *block, int type, int retval, blender::StringRef str, int x, int y, short width, short height, void *poin, float min, float max, std::optional< blender::StringRef > tip)
int UI_preview_tile_size_y(const int size_px=96)
int UI_preview_tile_size_x(const int size_px=96)
void UI_but_func_quick_tooltip_set(uiBut *but, std::function< std::string(const uiBut *but)> func)
void uiLayoutSetFixedSize(uiLayout *layout, bool fixed_size)
uiBlock * uiLayoutGetBlock(uiLayout *layout)
float uiLayoutGetUnitsX(uiLayout *layout)
int uiLayoutGetWidth(uiLayout *layout)
void UI_block_layout_set_current(uiBlock *block, uiLayout *layout)
virtual void build_grid_tile(const bContext &C, uiLayout &layout) const =0
std::optional< std::string > debug_name() const override
AbstractGridView & get_view() const
virtual std::unique_ptr< GridViewItemDropTarget > create_drop_target()
friend class AbstractGridView
AbstractGridViewItem(StringRef identifier)
std::unique_ptr< DropTargetInterface > create_item_drop_target() final
bool matches(const AbstractViewItem &other) const override
Map< StringRef, AbstractGridViewItem * > item_map_
ItemT & add_item(Args &&...args)
void set_tile_size(int tile_width, int tile_height)
int get_item_count() const
void foreach_filtered_item(ItemIterFn iter_fn) const
FunctionRef< void(AbstractGridViewItem &)> ItemIterFn
int get_item_count_filtered() const
void foreach_item(ItemIterFn iter_fn) const
std::optional< int > item_count_filtered_
const GridViewStyle & get_style() const
friend class AbstractGridViewItem
virtual void build_items()=0
Vector< std::unique_ptr< AbstractGridViewItem > > items_
void activate(bContext &C)
AbstractViewItem()=default
bool is_filtered_visible() const
uiButViewItem * view_item_but_
uiButViewItem * view_item_button() const
virtual std::optional< bool > should_be_active() const
const AbstractViewItem * search_highlight_item() const
void update_from_old(uiBlock &new_block)
virtual void change_state_delayed()
void register_item(AbstractViewItem &item)
void filter(std::optional< StringRef > filter_str)
void build_grid_view(const bContext &C, AbstractGridView &grid_view, uiLayout &layout, std::optional< StringRef > search_string={})
GridViewBuilder(uiBlock &block)
GridViewItemDropTarget(AbstractGridView &view)
GridViewLayoutBuilder(uiLayout &layout)
friend class GridViewBuilder
void build_from_view(const bContext &C, const AbstractGridView &grid_view, const View2D &v2d) const
PreviewGridItem(StringRef identifier, StringRef label, int preview_icon_id)
void set_is_active_fn(IsActiveFn fn)
void build_grid_tile_button(uiLayout &layout, BIFIconID override_preview_icon_id=ICON_NONE) const
std::function< void(bContext &C, PreviewGridItem &new_active)> ActivateFn
void set_on_activate_fn(ActivateFn fn)
std::function< bool()> IsActiveFn
void build_grid_tile(const bContext &C, uiLayout &layout) const override
void ui_def_but_icon(uiBut *but, const int icon, const int flag)
void ui_block_view_persistent_state_restore(const ARegion ®ion, const uiBlock &block, blender::ui::AbstractView &view)
static std::optional< int > find_filtered_item_index(const AbstractGridViewItem &item)
GridViewStyle(int width, int height)
blender::ui::AbstractViewItem * view_item
uiLayout & column(bool align)
uiLayout & row(bool align)