Blender V4.3
abstract_view.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "interface_intern.hh"
10
11#include "UI_abstract_view.hh"
12
13using namespace blender;
14
15namespace blender::ui {
16
18{
19 /* Actually modifies the item, not the view. But for the public API it "feels" a bit nicer to
20 * have the view base class register the items, rather than setting the view on the item. */
21 item.view_ = this;
22}
23
24/* ---------------------------------------------------------------------- */
29{
30 return is_reconstructed_;
31}
32
34{
35 const AbstractViewItem *found_item = nullptr;
36
37 this->foreach_view_item([&](const AbstractViewItem &item) {
38 if (!found_item && item.is_search_highlight()) {
39 found_item = &item;
40 }
41 });
42 return found_item;
43}
44
46{
47 uiBlock *old_block = new_block.oldblock;
48 if (!old_block) {
49 is_reconstructed_ = true;
50 return;
51 }
52
53 AbstractView *old_view = ui_block_view_find_matching_in_old_block(new_block, *this);
54 if (old_view == nullptr) {
55 /* Initial construction, nothing to update. */
56 is_reconstructed_ = true;
57 return;
58 }
59
60 /* Update own persistent data. */
61 prev_filter_string_ = old_view->prev_filter_string_;
62 /* Keep the rename buffer persistent while renaming! The rename button uses the buffer's
63 * pointer to identify itself over redraws. */
64 rename_buffer_ = std::move(old_view->rename_buffer_);
65 old_view->rename_buffer_ = nullptr;
66
67 this->update_children_from_old(*old_view);
68
69 /* Finished (re-)constructing the tree. */
70 is_reconstructed_ = true;
71}
72
75/* ---------------------------------------------------------------------- */
80{
82 this->is_reconstructed(),
83 "These state changes are supposed to be delayed until reconstruction is completed");
84
85/* Debug-only sanity check: Ensure only one item requests to be active. */
86#ifndef NDEBUG
87 bool has_active = false;
88 foreach_view_item([&has_active](AbstractViewItem &item) {
89 if (item.should_be_active().value_or(false)) {
90 BLI_assert_msg(
91 !has_active,
92 "Only one view item should ever return true for its `should_be_active()` method");
93 has_active = true;
94 }
95 });
96#endif
97
98 this->foreach_view_item([](AbstractViewItem &item) { item.change_state_delayed(); });
99}
100
103/* ---------------------------------------------------------------------- */
107std::unique_ptr<DropTargetInterface> AbstractView::create_drop_target()
108{
109 /* There's no drop target (and hence no drop support) by default. */
110 return nullptr;
111}
112
113bool AbstractView::listen(const wmNotifier & /*notifier*/) const
114{
115 /* Nothing by default. */
116 return false;
117}
118
120{
121 return false;
122}
123
124void AbstractView::draw_overlays(const ARegion & /*region*/, const uiBlock & /*block*/) const
125{
126 /* Nothing by default. */
127}
128
130{
131 return false;
132}
133
135{
136 BLI_assert_msg(false, "Unsupported for this view type");
137}
138
141/* ---------------------------------------------------------------------- */
145void AbstractView::filter(std::optional<StringRef> filter_str)
146{
147 needs_filtering_ = false;
148
149 if (!filter_str) {
150 return;
151 }
152
153 const bool is_empty = filter_str->is_empty();
154 const bool filter_changed = filter_str != prev_filter_string_;
155 prev_filter_string_ = *filter_str;
156
157 bool has_search_highlight = false;
158 this->foreach_view_item([&](AbstractViewItem &item) {
159 item.is_filtered_visible_ = is_empty ||
160 item.should_be_filtered_visible(StringRefNull(*filter_str));
161
162 if (filter_changed) {
163 item.is_highlighted_search_ = false;
164 /* On new filtering input, force the first visible item to be highlighted and in view, so
165 * enter activates it. */
166 if (item.is_filtered_visible_ && !has_search_highlight) {
167 item.is_highlighted_search_ = true;
168 has_search_highlight = true;
169 }
170 }
171 });
172}
173
174/* ---------------------------------------------------------------------- */
179{
180 return rename_buffer_ != nullptr;
181}
182
184{
185 if (this->is_renaming()) {
186 return false;
187 }
188
189 rename_buffer_ = std::make_unique<decltype(rename_buffer_)::element_type>();
190 return true;
191}
192
194{
196 rename_buffer_ = nullptr;
197}
198
200{
201 return *rename_buffer_;
202}
204{
205 return *rename_buffer_;
206}
207
208std::optional<rcti> AbstractView::get_bounds() const
209{
210 return bounds_;
211}
212
214{
215 return context_menu_title;
216}
217
218void AbstractView::set_context_menu_title(const std::string &title)
219{
220 context_menu_title = title;
221}
222
224{
225 return popup_keep_open_;
226}
227
229{
230 popup_keep_open_ = true;
231}
232
239} // namespace blender::ui
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
virtual bool should_be_filtered_visible(StringRefNull filter_string) const
virtual std::optional< bool > should_be_active() const
virtual bool supports_scrolling() const
virtual void draw_overlays(const ARegion &region, const uiBlock &block) const
const AbstractViewItem * search_highlight_item() const
virtual bool listen(const wmNotifier &) const
std::optional< rcti > get_bounds() const
void update_from_old(uiBlock &new_block)
virtual void change_state_delayed()
virtual std::unique_ptr< DropTargetInterface > create_drop_target()
virtual void foreach_view_item(FunctionRef< void(AbstractViewItem &)> iter_fn) const =0
virtual bool begin_filtering(const bContext &C) const
virtual void scroll(ViewScrollDirection direction)
virtual void update_children_from_old(const AbstractView &old_view)=0
void register_item(AbstractViewItem &item)
Span< char > get_rename_buffer() const
std::string get_context_menu_title() const
void filter(std::optional< StringRef > filter_str)
void set_context_menu_title(const std::string &title)
blender::ui::AbstractView * ui_block_view_find_matching_in_old_block(const uiBlock &new_block, const blender::ui::AbstractView &new_view)
uiBlock * oldblock