Blender  V3.3
abstract_view_item.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include "BKE_context.h"
8 
9 #include "BLI_listbase.h"
10 #include "BLI_string.h"
11 
12 #include "WM_api.h"
13 
14 #include "UI_interface.h"
15 #include "interface_intern.h"
16 
17 #include "UI_abstract_view.hh"
18 
19 namespace blender::ui {
20 
21 /* ---------------------------------------------------------------------- */
26 {
27  is_active_ = old.is_active_;
29 }
30 
33 /* ---------------------------------------------------------------------- */
38 {
39  /* No renaming by default. */
40  return false;
41 }
43 {
44  /* No renaming by default. */
45  return false;
46 }
47 
49 {
50  /* No rename string by default. */
51  return {};
52 }
53 
55 {
56  return is_renaming_;
57 }
58 
60 {
62  if (view.is_renaming() || !supports_renaming()) {
63  return;
64  }
65 
66  if (view.begin_renaming()) {
67  is_renaming_ = true;
68  }
69 
70  StringRef initial_str = get_rename_string();
71  std::copy(std::begin(initial_str), std::end(initial_str), std::begin(view.get_rename_buffer()));
72 }
73 
75 {
76  const AbstractView &view = get_view();
77  rename(view.get_rename_buffer().data());
78  end_renaming();
79 }
80 
82 {
83  if (!is_renaming()) {
84  return;
85  }
86 
87  is_renaming_ = false;
88 
90  view.end_renaming();
91 }
92 
94 {
95  /* A minimal sanity check, can't do much more here. */
96  BLI_assert(rename_but.type == UI_BTYPE_TEXT && rename_but.poin);
97 
98  LISTBASE_FOREACH (uiBut *, but, &rename_but.block->buttons) {
99  if (but->type != UI_BTYPE_VIEW_ITEM) {
100  continue;
101  }
102 
103  uiButViewItem *view_item_but = (uiButViewItem *)but;
104  AbstractViewItem *item = reinterpret_cast<AbstractViewItem *>(view_item_but->view_item);
105  const AbstractView &view = item->get_view();
106 
107  if (item->is_renaming() && (view.get_rename_buffer().data() == rename_but.poin)) {
108  return item;
109  }
110  }
111 
112  return nullptr;
113 }
114 
115 static void rename_button_fn(bContext *UNUSED(C), void *arg, char *UNUSED(origstr))
116 {
117  const uiBut *rename_but = static_cast<uiBut *>(arg);
118  AbstractViewItem *item = find_item_from_rename_button(*rename_but);
119  BLI_assert(item);
120  item->rename_apply();
121 }
122 
124 {
126  uiBut *rename_but = uiDefBut(&block,
128  1,
129  "",
130  0,
131  0,
132  UI_UNIT_X * 10,
133  UI_UNIT_Y,
134  view.get_rename_buffer().data(),
135  1.0f,
136  view.get_rename_buffer().size(),
137  0,
138  0,
139  "");
140 
141  /* Gotta be careful with what's passed to the `arg1` here. Any view data will be freed once the
142  * callback is executed. */
143  UI_but_func_rename_set(rename_but, rename_button_fn, rename_but);
144  UI_but_flag_disable(rename_but, UI_BUT_UNDO);
145 
146  const bContext *evil_C = reinterpret_cast<bContext *>(block.evil_C);
147  ARegion *region = CTX_wm_region(evil_C);
148  /* Returns false if the button was removed. */
149  if (UI_but_active_only(evil_C, region, &block, rename_but) == false) {
150  end_renaming();
151  }
152 }
153 
156 /* ---------------------------------------------------------------------- */
160 void AbstractViewItem::build_context_menu(bContext & /*C*/, uiLayout & /*column*/) const
161 {
162  /* No context menu by default. */
163 }
164 
167 /* ---------------------------------------------------------------------- */
171 std::unique_ptr<AbstractViewItemDragController> AbstractViewItem::create_drag_controller() const
172 {
173  /* There's no drag controller (and hence no drag support) by default. */
174  return nullptr;
175 }
176 
177 std::unique_ptr<AbstractViewItemDropController> AbstractViewItem::create_drop_controller() const
178 {
179  /* There's no drop controller (and hence no drop support) by default. */
180  return nullptr;
181 }
182 
184 {
185 }
186 
188 {
189  /* Do nothing by default. */
190 }
191 
193 {
194 }
195 
198 /* ---------------------------------------------------------------------- */
203 {
204  if (UNLIKELY(!view_)) {
205  throw std::runtime_error(
206  "Invalid state, item must be registered through AbstractView::register_item()");
207  }
208  return *view_;
209 }
210 
212 {
213  BLI_assert_msg(get_view().is_reconstructed(),
214  "State can't be queried until reconstruction is completed");
215  return is_active_;
216 }
217 
220 } // namespace blender::ui
221 
222 /* ---------------------------------------------------------------------- */
226 namespace blender::ui {
227 
233  public:
234  static bool matches(const AbstractViewItem &a, const AbstractViewItem &b)
235  {
236  if (typeid(a) != typeid(b)) {
237  return false;
238  }
239  /* TODO should match the view as well. */
240  return a.matches(b);
241  }
242 
243  static bool can_rename(const AbstractViewItem &item)
244  {
245  const AbstractView &view = item.get_view();
246  return !view.is_renaming() && item.supports_renaming();
247  }
248 
249  static bool drag_start(bContext &C, const AbstractViewItem &item)
250  {
251  const std::unique_ptr<AbstractViewItemDragController> drag_controller =
252  item.create_drag_controller();
253  if (!drag_controller) {
254  return false;
255  }
256 
258  ICON_NONE,
259  drag_controller->get_drag_type(),
260  drag_controller->create_drag_data(),
261  0,
263  drag_controller->on_drag_start();
264 
265  return true;
266  }
267 
268  static bool can_drop(const AbstractViewItem &item,
269  const wmDrag &drag,
270  const char **r_disabled_hint)
271  {
272  const std::unique_ptr<AbstractViewItemDropController> drop_controller =
273  item.create_drop_controller();
274  if (!drop_controller) {
275  return false;
276  }
277 
278  return drop_controller->can_drop(drag, r_disabled_hint);
279  }
280 
281  static std::string drop_tooltip(const AbstractViewItem &item, const wmDrag &drag)
282  {
283  const std::unique_ptr<AbstractViewItemDropController> drop_controller =
284  item.create_drop_controller();
285  if (!drop_controller) {
286  return {};
287  }
288 
289  return drop_controller->drop_tooltip(drag);
290  }
291 
292  static bool drop_handle(bContext &C, const AbstractViewItem &item, const ListBase &drags)
293  {
294  std::unique_ptr<AbstractViewItemDropController> drop_controller =
295  item.create_drop_controller();
296 
297  const char *disabled_hint_dummy = nullptr;
298  LISTBASE_FOREACH (const wmDrag *, drag, &drags) {
299  if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) {
300  return drop_controller->on_drop(&C, *drag);
301  }
302  }
303 
304  return false;
305  }
306 };
307 
308 } // namespace blender::ui
309 
310 using namespace blender::ui;
311 
312 bool UI_view_item_is_active(const uiViewItemHandle *item_handle)
313 {
314  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
315  return item.is_active();
316 }
317 
318 bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle)
319 {
320  const AbstractViewItem &a = reinterpret_cast<const AbstractViewItem &>(*a_handle);
321  const AbstractViewItem &b = reinterpret_cast<const AbstractViewItem &>(*b_handle);
323 }
324 
326 {
327  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
328  return ViewItemAPIWrapper::can_rename(item);
329 }
330 
332 {
333  AbstractViewItem &item = reinterpret_cast<AbstractViewItem &>(*item_handle);
334  item.begin_renaming();
335 }
336 
338  const uiViewItemHandle *item_handle,
339  uiLayout *column)
340 {
341  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_handle);
342  item.build_context_menu(*C, *column);
343 }
344 
346 {
347  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
348  return ViewItemAPIWrapper::drag_start(*C, item);
349 }
350 
352  const wmDrag *drag,
353  const char **r_disabled_hint)
354 {
355  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
356  return ViewItemAPIWrapper::can_drop(item, *drag, r_disabled_hint);
357 }
358 
359 char *UI_view_item_drop_tooltip(const uiViewItemHandle *item_, const wmDrag *drag)
360 {
361  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
362 
363  const std::string tooltip = ViewItemAPIWrapper::drop_tooltip(item, *drag);
364  return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str());
365 }
366 
367 bool UI_view_item_drop_handle(bContext *C, const uiViewItemHandle *item_, const ListBase *drags)
368 {
369  const AbstractViewItem &item = reinterpret_cast<const AbstractViewItem &>(*item_);
370  return ViewItemAPIWrapper::drop_handle(*C, item, *drags);
371 }
372 
struct ARegion * CTX_wm_region(const bContext *C)
Definition: context.c:749
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL() ATTR_MALLOC
Definition: string.c:42
#define UNUSED(x)
#define UNLIKELY(x)
static AppView * view
#define C
Definition: RandGen.cpp:25
void UI_but_flag_disable(uiBut *but, int flag)
Definition: interface.cc:5863
#define UI_UNIT_Y
@ UI_BUT_UNDO
Definition: UI_interface.h:205
uiBut * uiDefBut(uiBlock *block, int type, int retval, const char *str, int x, int y, short width, short height, void *poin, float min, float max, float a1, float a2, const char *tip)
Definition: interface.cc:4806
bool UI_but_active_only(const struct bContext *C, struct ARegion *region, uiBlock *block, uiBut *but)
void UI_but_func_rename_set(uiBut *but, uiButHandleRenameFunc func, void *arg1)
Definition: interface.cc:5983
#define UI_UNIT_X
struct uiViewItemHandle uiViewItemHandle
Definition: UI_interface.h:78
@ UI_BTYPE_TEXT
Definition: UI_interface.h:332
@ UI_BTYPE_VIEW_ITEM
Definition: UI_interface.h:393
@ WM_DRAG_FREE_DATA
Definition: WM_types.h:1059
char * UI_view_item_drop_tooltip(const uiViewItemHandle *item_, const wmDrag *drag)
bool UI_view_item_is_active(const uiViewItemHandle *item_handle)
bool UI_view_item_can_drop(const uiViewItemHandle *item_, const wmDrag *drag, const char **r_disabled_hint)
bool UI_view_item_matches(const uiViewItemHandle *a_handle, const uiViewItemHandle *b_handle)
bool UI_view_item_drop_handle(bContext *C, const uiViewItemHandle *item_, const ListBase *drags)
bool UI_view_item_drag_start(bContext *C, const uiViewItemHandle *item_)
bool UI_view_item_can_rename(const uiViewItemHandle *item_handle)
void UI_view_item_context_menu_build(bContext *C, const uiViewItemHandle *item_handle, uiLayout *column)
void UI_view_item_begin_rename(uiViewItemHandle *item_handle)
virtual void update_from_old(const AbstractViewItem &old)
void add_rename_button(uiBlock &block)
AbstractView & get_view() const
virtual bool supports_renaming() const
virtual bool rename(StringRefNull new_name)
virtual void build_context_menu(bContext &C, uiLayout &column) const
virtual StringRef get_rename_string() const
virtual std::unique_ptr< AbstractViewItemDropController > create_drop_controller() const
virtual std::unique_ptr< AbstractViewItemDragController > create_drag_controller() const
static bool drop_handle(bContext &C, const AbstractViewItem &item, const ListBase &drags)
static bool can_drop(const AbstractViewItem &item, const wmDrag &drag, const char **r_disabled_hint)
static bool can_rename(const AbstractViewItem &item)
static std::string drop_tooltip(const AbstractViewItem &item, const wmDrag &drag)
static bool matches(const AbstractViewItem &a, const AbstractViewItem &b)
static bool drag_start(bContext &C, const AbstractViewItem &item)
static unsigned a[3]
Definition: RandGen.cpp:78
static void rename_button_fn(bContext *UNUSED(C), void *arg, char *UNUSED(origstr))
static AbstractViewItem * find_item_from_rename_button(const uiBut &rename_but)
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
static void copy(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node)
ListBase buttons
void * evil_C
uiViewItemHandle * view_item
eButType type
uiBlock * block
char * poin
void WM_event_start_drag(bContext *C, int icon, int type, void *poin, double value, unsigned int flags)
Definition: wm_dragdrop.cc:237