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::add_grid_tile_button(
uiBlock &block)
167 throw std::runtime_error(
168 "Invalid state, item must be added through AbstractGridView::add_item()");
208 const int cols_per_row_ = 0;
211 std::optional<IndexRange> visible_items_range_;
226 void add_spacer_button(
uiBlock &block,
int row_count)
const;
232 const int cols_per_row,
234 : grid_view_(grid_view), style_(grid_view.get_style()), cols_per_row_(cols_per_row)
237 visible_items_range_ = this->get_visible_range(v2d, force_visible_item);
246 std::optional<int> index;
250 if (&item == &iter_item) {
259IndexRange BuildOnlyVisibleButtonsHelper::get_visible_range(
260 const View2D &v2d,
const AbstractGridViewItem *force_visible_item)
const
264 int first_idx_in_view = 0;
267 if (!
IS_EQF(scroll_ofs_y, 0)) {
268 const int scrolled_away_rows = int(scroll_ofs_y) / style_.
tile_height;
270 first_idx_in_view = scrolled_away_rows * cols_per_row_;
274 const int count_rows_in_view = std::max(view_height / style_.
tile_height, 1);
275 const int max_items_in_view = (count_rows_in_view + 1) * cols_per_row_;
278 IndexRange visible_items(first_idx_in_view, max_items_in_view);
281 if (force_visible_item && force_visible_item->is_filtered_visible()) {
283 if (!visible_items.contains(*item_idx)) {
285 return IndexRange((item_idx == 0) ? 0 : *item_idx % cols_per_row_, max_items_in_view);
290 return visible_items;
295 return !visible_items_range_ || visible_items_range_->contains(item_idx);
300 if (!visible_items_range_ || visible_items_range_->is_empty()) {
303 const int first_idx_in_view = visible_items_range_->first();
304 if (first_idx_in_view < 1) {
307 const int tot_tiles_before_visible = first_idx_in_view;
308 const int scrolled_away_rows = tot_tiles_before_visible / cols_per_row_;
309 this->add_spacer_button(block, scrolled_away_rows);
314 if (!visible_items_range_ || visible_items_range_->is_empty()) {
317 const int last_item_idx = grid_view_.get_item_count_filtered() - 1;
318 const int last_visible_idx = visible_items_range_->last();
320 if (last_item_idx > last_visible_idx) {
321 const int remaining_rows = (cols_per_row_ > 0) ?
ceilf((last_item_idx - last_visible_idx) /
322 float(cols_per_row_)) :
324 BuildOnlyVisibleButtonsHelper::add_spacer_button(block, remaining_rows);
328void BuildOnlyVisibleButtonsHelper::add_spacer_button(
uiBlock &block,
const int row_count)
const
332 for (
int remaining_rows = row_count; remaining_rows > 0;) {
333 const short row_count_this_iter = std::min(
334 std::numeric_limits<short>::max() / style_.
tile_height, remaining_rows);
348 remaining_rows -= row_count_this_iter;
374void GridViewLayoutBuilder::build_grid_tile(
const bContext &
C,
381 item.add_grid_tile_button(block_);
389 uiLayout *parent_layout = this->current_layout();
397 const int guessed_layout_width = (parent_layout->
ui_units_x() > 0) ?
399 parent_layout->
width();
400 const int cols_per_row = std::max(guessed_layout_width / style.
tile_width, 1);
406 v2d, grid_view, cols_per_row, search_highlight_item);
420 if ((item_idx % cols_per_row) == 0) {
421 row = &layout.
row(
true);
424 this->build_grid_tile(
C, *row, item);
433uiLayout *GridViewLayoutBuilder::current_layout()
const
445 std::optional<StringRef> search_string)
455 grid_view.
filter(search_string);
472 BIFIconID override_preview_icon_id)
const
522void 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)
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)
uiBut * uiDefBut(uiBlock *block, uiButTypeWithPointerType but_and_ptr_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)
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_
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)
void block_layout_set_current(uiBlock *block, uiLayout *layout)
GridViewStyle(int width, int height)
blender::ui::AbstractViewItem * view_item
void fixed_size_set(bool fixed_size)
uiLayout & column(bool align)
uiLayout & row(bool align)