Cleanup: Various cleanups to the tree-view API
* Correct URL for documentation (was changed recently). * Add comments. * Reevaluate and update which functions are public, protected or private. * Reorder functions and classes to be more logical and readable. * Add helper class for the public item API so individual functions it uses can be made protected/private (the helper class is a friend). Also allows splitting API implementation from the C-API. * Move internal layout builder helper class to the source file, out of the header. * More consistent naming. * Add alias for item-container, so it's more clear how it can be used. * Use const. * Remove unnecessary forward declaration.
This commit is contained in:
parent
9183f9f860
commit
69f55b1b62
|
@ -3286,7 +3286,7 @@ char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item, const str
|
|||
* \return True if the drop was handled by the tree-view item.
|
||||
*/
|
||||
bool UI_tree_view_item_drop_handle(struct bContext *C,
|
||||
uiTreeViewItemHandle *item_,
|
||||
const uiTreeViewItemHandle *item_,
|
||||
const struct ListBase *drags);
|
||||
/**
|
||||
* Can \a item_handle be renamed right now? Not that this isn't just a mere wrapper around
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
/** \file
|
||||
* \ingroup editorui
|
||||
*
|
||||
* API for simple creation of tree UIs supporting advanced features.
|
||||
* https://wiki.blender.org/wiki/Source/Interface/Views
|
||||
* API for simple creation of tree UIs supporting typically needed features.
|
||||
* https://wiki.blender.org/wiki/Source/Interface/Views/Tree_Views
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
@ -36,7 +36,6 @@
|
|||
#include "UI_resources.h"
|
||||
|
||||
struct bContext;
|
||||
struct PointerRNA;
|
||||
struct uiBlock;
|
||||
struct uiBut;
|
||||
struct uiButTreeRow;
|
||||
|
@ -53,14 +52,17 @@ class AbstractTreeViewItemDragController;
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Tree-View Item Container
|
||||
*
|
||||
* Base class for tree-view and tree-view items, so both can contain children.
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Helper base class to expose common child-item data and functionality to both #AbstractTreeView
|
||||
* and #AbstractTreeViewItem.
|
||||
* Both the tree-view (as the root of the tree) and the items can have children. This is the base
|
||||
* class for both, to store and manage child items. Children are owned by their parent container
|
||||
* (tree-view or item).
|
||||
*
|
||||
* That means this type can be used whenever either a #AbstractTreeView or a
|
||||
* #AbstractTreeViewItem is needed.
|
||||
* That means this type can be used whenever either an #AbstractTreeView or an
|
||||
* #AbstractTreeViewItem is needed, but the #TreeViewOrItem alias is a better name to use then.
|
||||
*/
|
||||
class TreeViewItemContainer {
|
||||
friend class AbstractTreeView;
|
||||
|
@ -112,43 +114,10 @@ class TreeViewItemContainer {
|
|||
ENUM_OPERATORS(TreeViewItemContainer::IterOptions,
|
||||
TreeViewItemContainer::IterOptions::SkipCollapsed);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Tree-View Builders
|
||||
* \{ */
|
||||
|
||||
class TreeViewBuilder {
|
||||
uiBlock &block_;
|
||||
|
||||
public:
|
||||
TreeViewBuilder(uiBlock &block);
|
||||
|
||||
void build_tree_view(AbstractTreeView &tree_view);
|
||||
};
|
||||
|
||||
class TreeViewLayoutBuilder {
|
||||
uiBlock &block_;
|
||||
|
||||
friend TreeViewBuilder;
|
||||
|
||||
public:
|
||||
void build_row(AbstractTreeViewItem &item) const;
|
||||
uiBlock &block() const;
|
||||
uiLayout *current_layout() const;
|
||||
|
||||
private:
|
||||
/* Created through #TreeViewBuilder. */
|
||||
TreeViewLayoutBuilder(uiBlock &block);
|
||||
|
||||
/**
|
||||
* Moves the button following the last added chevron closer to the list item.
|
||||
*
|
||||
* Iterates backwards over buttons until finding the tree-row button, which is assumed to be the
|
||||
* first button added for the row, and can act as a delimiter that way.
|
||||
*/
|
||||
static void polish_layout(const uiBlock &block);
|
||||
};
|
||||
/** The container class is the base for both the tree-view and the items. This alias gives it a
|
||||
* clearer name for handles that accept both. Use whenever something wants to act on child-items,
|
||||
* irrespective of if they are stored at root level or as children of some other item. */
|
||||
using TreeViewOrItem = TreeViewItemContainer;
|
||||
|
||||
/** \} */
|
||||
|
||||
|
@ -157,8 +126,8 @@ class TreeViewLayoutBuilder {
|
|||
* \{ */
|
||||
|
||||
class AbstractTreeView : public TreeViewItemContainer {
|
||||
friend AbstractTreeViewItem;
|
||||
friend TreeViewBuilder;
|
||||
friend class AbstractTreeViewItem;
|
||||
friend class TreeViewBuilder;
|
||||
|
||||
/**
|
||||
* Only one item can be renamed at a time. So the tree is informed about the renaming state to
|
||||
|
@ -175,15 +144,16 @@ class AbstractTreeView : public TreeViewItemContainer {
|
|||
|
||||
/** Only one item can be renamed at a time. */
|
||||
bool is_renaming() const;
|
||||
|
||||
protected:
|
||||
virtual void build_tree() = 0;
|
||||
|
||||
/**
|
||||
* Check if the tree is fully (re-)constructed. That means, both #build_tree() and
|
||||
* #update_from_old() have finished.
|
||||
*/
|
||||
bool is_reconstructed() const;
|
||||
|
||||
protected:
|
||||
virtual void build_tree() = 0;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Match the tree-view against an earlier version of itself (if any) and copy the old UI state
|
||||
|
@ -191,10 +161,10 @@ class AbstractTreeView : public TreeViewItemContainer {
|
|||
* #AbstractTreeViewItem.update_from_old().
|
||||
*/
|
||||
void update_from_old(uiBlock &new_block);
|
||||
static void update_children_from_old_recursive(const TreeViewItemContainer &new_items,
|
||||
const TreeViewItemContainer &old_items);
|
||||
static void update_children_from_old_recursive(const TreeViewOrItem &new_items,
|
||||
const TreeViewOrItem &old_items);
|
||||
static AbstractTreeViewItem *find_matching_child(const AbstractTreeViewItem &lookup_item,
|
||||
const TreeViewItemContainer &items);
|
||||
const TreeViewOrItem &items);
|
||||
|
||||
/**
|
||||
* Items may want to do additional work when state changes. But these state changes can only be
|
||||
|
@ -202,7 +172,6 @@ class AbstractTreeView : public TreeViewItemContainer {
|
|||
* the actual state changes are done in a delayed manner through this function.
|
||||
*/
|
||||
void change_state_delayed();
|
||||
void build_layout_from_tree(const TreeViewLayoutBuilder &builder);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -221,17 +190,18 @@ class AbstractTreeView : public TreeViewItemContainer {
|
|||
class AbstractTreeViewItem : public TreeViewItemContainer {
|
||||
friend class AbstractTreeView;
|
||||
friend class TreeViewLayoutBuilder;
|
||||
/* Higher-level API. */
|
||||
friend class TreeViewItemAPIWrapper;
|
||||
|
||||
public:
|
||||
private:
|
||||
bool is_open_ = false;
|
||||
bool is_active_ = false;
|
||||
bool is_renaming_ = false;
|
||||
|
||||
protected:
|
||||
/** This label is used for identifying an item (together with its parent's labels). */
|
||||
/** This label is used for identifying an item within its parent. */
|
||||
std::string label_{};
|
||||
/** Every item gets a button of type during the layout building #UI_BTYPE_TREEROW. */
|
||||
/** Every visible item gets a button of type #UI_BTYPE_TREEROW during the layout building. */
|
||||
uiButTreeRow *tree_row_but_ = nullptr;
|
||||
|
||||
public:
|
||||
|
@ -240,28 +210,59 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
|
|||
virtual void build_row(uiLayout &row) = 0;
|
||||
virtual void build_context_menu(bContext &C, uiLayout &column) const;
|
||||
|
||||
AbstractTreeView &get_tree_view() const;
|
||||
|
||||
void begin_renaming();
|
||||
void toggle_collapsed();
|
||||
void set_collapsed(bool collapsed);
|
||||
/**
|
||||
* Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
* can't be sure about the item state.
|
||||
*/
|
||||
bool is_collapsed() const;
|
||||
/**
|
||||
* Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
* can't be sure about the item state.
|
||||
*/
|
||||
bool is_active() const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Called when the items state changes from inactive to active.
|
||||
*/
|
||||
virtual void on_activate();
|
||||
/**
|
||||
* If the result is not empty, it controls whether the item should be active or not,
|
||||
* usually depending on the data that the view represents.
|
||||
*/
|
||||
virtual std::optional<bool> should_be_active() const;
|
||||
|
||||
/**
|
||||
* Queries if the tree-view item supports renaming in principle. Renaming may still fail, e.g. if
|
||||
* another item is already being renamed.
|
||||
*/
|
||||
virtual bool can_rename() const;
|
||||
virtual bool supports_renaming() const;
|
||||
/**
|
||||
* Try renaming the item, or the data it represents. Can assume
|
||||
* #AbstractTreeViewItem::can_rename() returned true. Sub-classes that override this should
|
||||
* usually call this, unless they have a custom #AbstractTreeViewItem.matches().
|
||||
* #AbstractTreeViewItem::supports_renaming() returned true. Sub-classes that override this
|
||||
* should usually call this, unless they have a custom #AbstractTreeViewItem.matches().
|
||||
*
|
||||
* \return True if the renaming was successful.
|
||||
*/
|
||||
virtual bool rename(StringRefNull new_name);
|
||||
|
||||
/**
|
||||
* Return whether the item can be collapsed. Used to disable collapsing for items with children.
|
||||
*/
|
||||
virtual bool supports_collapsing() const;
|
||||
|
||||
/**
|
||||
* Copy persistent state (e.g. is-collapsed flag, selection, etc.) from a matching item of
|
||||
* the last redraw to this item. If sub-classes introduce more advanced state they should
|
||||
* override this and make it update their state accordingly.
|
||||
*/
|
||||
virtual void update_from_old(const AbstractTreeViewItem &old);
|
||||
|
||||
/**
|
||||
* Compare this item to \a other to check if they represent the same data.
|
||||
* Used to recognize an item from a previous redraw, to be able to keep its state (e.g.
|
||||
|
@ -285,39 +286,6 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
|
|||
*/
|
||||
virtual std::unique_ptr<AbstractTreeViewItemDropController> create_drop_controller() const;
|
||||
|
||||
void begin_renaming();
|
||||
void end_renaming();
|
||||
|
||||
AbstractTreeView &get_tree_view() const;
|
||||
int count_parents() const;
|
||||
void deactivate();
|
||||
/**
|
||||
* Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
* can't be sure about the item state.
|
||||
*/
|
||||
bool is_active() const;
|
||||
/**
|
||||
* Can be called from the #AbstractTreeViewItem::build_row() implementation, but not earlier. The
|
||||
* hovered state can't be queried reliably otherwise.
|
||||
* Note that this does a linear lookup in the old block, so isn't too great performance-wise.
|
||||
*/
|
||||
bool is_hovered() const;
|
||||
void toggle_collapsed();
|
||||
/**
|
||||
* Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise we
|
||||
* can't be sure about the item state.
|
||||
*/
|
||||
bool is_collapsed() const;
|
||||
void set_collapsed(bool collapsed);
|
||||
bool is_collapsible() const;
|
||||
bool is_renaming() const;
|
||||
|
||||
void ensure_parents_uncollapsed();
|
||||
bool matches_including_parents(const AbstractTreeViewItem &other) const;
|
||||
|
||||
uiButTreeRow *tree_row_button();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Activates this item, deactivates other items, calls the #AbstractTreeViewItem::on_activate()
|
||||
* function and ensures this item's parents are not collapsed (so the item is visible).
|
||||
|
@ -325,17 +293,20 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
|
|||
* actual item state is unknown, possibly calling state-change update functions incorrectly.
|
||||
*/
|
||||
void activate();
|
||||
void deactivate();
|
||||
|
||||
/**
|
||||
* If the result is not empty, it controls whether the item should be active or not,
|
||||
* usually depending on the data that the view represents.
|
||||
* Can be called from the #AbstractTreeViewItem::build_row() implementation, but not earlier. The
|
||||
* hovered state can't be queried reliably otherwise.
|
||||
* Note that this does a linear lookup in the old block, so isn't too great performance-wise.
|
||||
*/
|
||||
virtual std::optional<bool> should_be_active() const;
|
||||
bool is_hovered() const;
|
||||
bool is_collapsible() const;
|
||||
bool is_renaming() const;
|
||||
|
||||
/**
|
||||
* Return whether the item can be collapsed. Used to disable collapsing for items with children.
|
||||
*/
|
||||
virtual bool supports_collapsing() const;
|
||||
void ensure_parents_uncollapsed();
|
||||
|
||||
uiButTreeRow *tree_row_button();
|
||||
|
||||
private:
|
||||
static void rename_button_fn(bContext *, void *, char *);
|
||||
|
@ -346,13 +317,16 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
|
|||
|
||||
/** See #AbstractTreeView::change_state_delayed() */
|
||||
void change_state_delayed();
|
||||
void end_renaming();
|
||||
|
||||
void add_treerow_button(uiBlock &block);
|
||||
void add_indent(uiLayout &row) const;
|
||||
void add_collapse_chevron(uiBlock &block) const;
|
||||
void add_rename_button(uiLayout &row);
|
||||
|
||||
bool matches_including_parents(const AbstractTreeViewItem &other) const;
|
||||
bool has_active_child() const;
|
||||
int count_parents() const;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
@ -464,6 +438,21 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
|
|||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/** \name Tree-View Builder
|
||||
* \{ */
|
||||
|
||||
class TreeViewBuilder {
|
||||
uiBlock &block_;
|
||||
|
||||
public:
|
||||
TreeViewBuilder(uiBlock &block);
|
||||
|
||||
void build_tree_view(AbstractTreeView &tree_view);
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
template<class ItemT, typename... Args>
|
||||
|
|
|
@ -87,19 +87,6 @@ bool AbstractTreeView::is_renaming() const
|
|||
return rename_buffer_ != nullptr;
|
||||
}
|
||||
|
||||
void AbstractTreeView::build_layout_from_tree(const TreeViewLayoutBuilder &builder)
|
||||
{
|
||||
uiLayout *prev_layout = builder.current_layout();
|
||||
|
||||
uiLayout *box = uiLayoutBox(prev_layout);
|
||||
uiLayoutColumn(box, false);
|
||||
|
||||
foreach_item([&builder](AbstractTreeViewItem &item) { builder.build_row(item); },
|
||||
IterOptions::SkipCollapsed);
|
||||
|
||||
UI_block_layout_set_current(&builder.block(), prev_layout);
|
||||
}
|
||||
|
||||
void AbstractTreeView::update_from_old(uiBlock &new_block)
|
||||
{
|
||||
uiBlock *old_block = new_block.oldblock;
|
||||
|
@ -130,8 +117,8 @@ void AbstractTreeView::update_from_old(uiBlock &new_block)
|
|||
is_reconstructed_ = true;
|
||||
}
|
||||
|
||||
void AbstractTreeView::update_children_from_old_recursive(const TreeViewItemContainer &new_items,
|
||||
const TreeViewItemContainer &old_items)
|
||||
void AbstractTreeView::update_children_from_old_recursive(const TreeViewOrItem &new_items,
|
||||
const TreeViewOrItem &old_items)
|
||||
{
|
||||
for (const auto &new_item : new_items.children_) {
|
||||
AbstractTreeViewItem *matching_old_item = find_matching_child(*new_item, old_items);
|
||||
|
@ -147,7 +134,7 @@ void AbstractTreeView::update_children_from_old_recursive(const TreeViewItemCont
|
|||
}
|
||||
|
||||
AbstractTreeViewItem *AbstractTreeView::find_matching_child(
|
||||
const AbstractTreeViewItem &lookup_item, const TreeViewItemContainer &items)
|
||||
const AbstractTreeViewItem &lookup_item, const TreeViewOrItem &items)
|
||||
{
|
||||
for (const auto &iter_item : items.children_) {
|
||||
if (lookup_item.matches(*iter_item)) {
|
||||
|
@ -380,7 +367,7 @@ std::unique_ptr<AbstractTreeViewItemDropController> AbstractTreeViewItem::create
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool AbstractTreeViewItem::can_rename() const
|
||||
bool AbstractTreeViewItem::supports_renaming() const
|
||||
{
|
||||
/* No renaming by default. */
|
||||
return false;
|
||||
|
@ -414,7 +401,7 @@ bool AbstractTreeViewItem::matches(const AbstractTreeViewItem &other) const
|
|||
void AbstractTreeViewItem::begin_renaming()
|
||||
{
|
||||
AbstractTreeView &tree_view = get_tree_view();
|
||||
if (tree_view.is_renaming() || !can_rename()) {
|
||||
if (tree_view.is_renaming() || !supports_renaming()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -444,7 +431,7 @@ AbstractTreeView &AbstractTreeViewItem::get_tree_view() const
|
|||
int AbstractTreeViewItem::count_parents() const
|
||||
{
|
||||
int i = 0;
|
||||
for (TreeViewItemContainer *parent = parent_; parent; parent = parent->parent_) {
|
||||
for (AbstractTreeViewItem *parent = parent_; parent; parent = parent->parent_) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
|
@ -587,24 +574,42 @@ AbstractTreeViewItemDropController::AbstractTreeViewItemDropController(AbstractT
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
TreeViewBuilder::TreeViewBuilder(uiBlock &block) : block_(block)
|
||||
{
|
||||
}
|
||||
class TreeViewLayoutBuilder {
|
||||
uiBlock &block_;
|
||||
|
||||
void TreeViewBuilder::build_tree_view(AbstractTreeView &tree_view)
|
||||
{
|
||||
tree_view.build_tree();
|
||||
tree_view.update_from_old(block_);
|
||||
tree_view.change_state_delayed();
|
||||
tree_view.build_layout_from_tree(TreeViewLayoutBuilder(block_));
|
||||
}
|
||||
friend TreeViewBuilder;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
public:
|
||||
void build_from_tree(const AbstractTreeView &tree_view);
|
||||
void build_row(AbstractTreeViewItem &item) const;
|
||||
|
||||
uiBlock &block() const;
|
||||
uiLayout *current_layout() const;
|
||||
|
||||
private:
|
||||
/* Created through #TreeViewBuilder. */
|
||||
TreeViewLayoutBuilder(uiBlock &block);
|
||||
|
||||
static void polish_layout(const uiBlock &block);
|
||||
};
|
||||
|
||||
TreeViewLayoutBuilder::TreeViewLayoutBuilder(uiBlock &block) : block_(block)
|
||||
{
|
||||
}
|
||||
|
||||
void TreeViewLayoutBuilder::build_from_tree(const AbstractTreeView &tree_view)
|
||||
{
|
||||
uiLayout *prev_layout = current_layout();
|
||||
|
||||
uiLayout *box = uiLayoutBox(prev_layout);
|
||||
uiLayoutColumn(box, false);
|
||||
|
||||
tree_view.foreach_item([this](AbstractTreeViewItem &item) { build_row(item); },
|
||||
AbstractTreeView::IterOptions::SkipCollapsed);
|
||||
|
||||
UI_block_layout_set_current(&block(), prev_layout);
|
||||
}
|
||||
|
||||
void TreeViewLayoutBuilder::polish_layout(const uiBlock &block)
|
||||
{
|
||||
LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block.buttons) {
|
||||
|
@ -664,6 +669,22 @@ uiLayout *TreeViewLayoutBuilder::current_layout() const
|
|||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
TreeViewBuilder::TreeViewBuilder(uiBlock &block) : block_(block)
|
||||
{
|
||||
}
|
||||
|
||||
void TreeViewBuilder::build_tree_view(AbstractTreeView &tree_view)
|
||||
{
|
||||
tree_view.build_tree();
|
||||
tree_view.update_from_old(block_);
|
||||
tree_view.change_state_delayed();
|
||||
|
||||
TreeViewLayoutBuilder builder(block_);
|
||||
builder.build_from_tree(tree_view);
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
BasicTreeViewItem::BasicTreeViewItem(StringRef label, BIFIconID icon_) : icon(icon_)
|
||||
{
|
||||
label_ = label;
|
||||
|
@ -710,8 +731,92 @@ std::optional<bool> BasicTreeViewItem::should_be_active() const
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Helper for a public (C-)API, presenting higher level functionality. Has access to internal
|
||||
* data/functionality (friend of #AbstractTreeViewItem), which is sometimes needed when
|
||||
* functionality of the API needs to be constructed from multiple internal conditions and/or
|
||||
* functions that on their own shouldn't be part of the API.
|
||||
*/
|
||||
class TreeViewItemAPIWrapper {
|
||||
public:
|
||||
static bool matches(const AbstractTreeViewItem &a, const AbstractTreeViewItem &b)
|
||||
{
|
||||
/* TODO should match the tree-view as well. */
|
||||
return a.matches_including_parents(b);
|
||||
}
|
||||
|
||||
static bool drag_start(bContext &C, const AbstractTreeViewItem &item)
|
||||
{
|
||||
const std::unique_ptr<AbstractTreeViewItemDragController> drag_controller =
|
||||
item.create_drag_controller();
|
||||
if (!drag_controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WM_event_start_drag(&C,
|
||||
ICON_NONE,
|
||||
drag_controller->get_drag_type(),
|
||||
drag_controller->create_drag_data(),
|
||||
0,
|
||||
WM_DRAG_FREE_DATA);
|
||||
drag_controller->on_drag_start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool can_drop(const AbstractTreeViewItem &item,
|
||||
const wmDrag &drag,
|
||||
const char **r_disabled_hint)
|
||||
{
|
||||
const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
if (!drop_controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drop_controller->can_drop(drag, r_disabled_hint);
|
||||
}
|
||||
|
||||
static std::string drop_tooltip(const AbstractTreeViewItem &item, const wmDrag &drag)
|
||||
{
|
||||
const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
if (!drop_controller) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return drop_controller->drop_tooltip(drag);
|
||||
}
|
||||
|
||||
static bool drop_handle(bContext &C, const AbstractTreeViewItem &item, const ListBase &drags)
|
||||
{
|
||||
std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
|
||||
const char *disabled_hint_dummy = nullptr;
|
||||
LISTBASE_FOREACH (const wmDrag *, drag, &drags) {
|
||||
if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) {
|
||||
return drop_controller->on_drop(&C, *drag);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool can_rename(const AbstractTreeViewItem &item)
|
||||
{
|
||||
const AbstractTreeView &tree_view = item.get_tree_view();
|
||||
return !tree_view.is_renaming() && item.supports_renaming();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace blender::ui
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* C-API */
|
||||
|
||||
using namespace blender::ui;
|
||||
|
||||
bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item_handle)
|
||||
|
@ -725,28 +830,13 @@ bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle,
|
|||
{
|
||||
const AbstractTreeViewItem &a = reinterpret_cast<const AbstractTreeViewItem &>(*a_handle);
|
||||
const AbstractTreeViewItem &b = reinterpret_cast<const AbstractTreeViewItem &>(*b_handle);
|
||||
/* TODO should match the tree-view as well. */
|
||||
return a.matches_including_parents(b);
|
||||
return TreeViewItemAPIWrapper::matches(a, b);
|
||||
}
|
||||
|
||||
bool UI_tree_view_item_drag_start(bContext *C, uiTreeViewItemHandle *item_)
|
||||
{
|
||||
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
|
||||
const std::unique_ptr<AbstractTreeViewItemDragController> drag_controller =
|
||||
item.create_drag_controller();
|
||||
if (!drag_controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WM_event_start_drag(C,
|
||||
ICON_NONE,
|
||||
drag_controller->get_drag_type(),
|
||||
drag_controller->create_drag_data(),
|
||||
0,
|
||||
WM_DRAG_FREE_DATA);
|
||||
drag_controller->on_drag_start();
|
||||
|
||||
return true;
|
||||
return TreeViewItemAPIWrapper::drag_start(*C, item);
|
||||
}
|
||||
|
||||
bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_,
|
||||
|
@ -754,50 +844,29 @@ bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_,
|
|||
const char **r_disabled_hint)
|
||||
{
|
||||
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
|
||||
const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
if (!drop_controller) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return drop_controller->can_drop(*drag, r_disabled_hint);
|
||||
return TreeViewItemAPIWrapper::can_drop(item, *drag, r_disabled_hint);
|
||||
}
|
||||
|
||||
char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_, const wmDrag *drag)
|
||||
{
|
||||
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
|
||||
const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
if (!drop_controller) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return BLI_strdup(drop_controller->drop_tooltip(*drag).c_str());
|
||||
const std::string tooltip = TreeViewItemAPIWrapper::drop_tooltip(item, *drag);
|
||||
return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str());
|
||||
}
|
||||
|
||||
bool UI_tree_view_item_drop_handle(struct bContext *C,
|
||||
uiTreeViewItemHandle *item_,
|
||||
bool UI_tree_view_item_drop_handle(bContext *C,
|
||||
const uiTreeViewItemHandle *item_,
|
||||
const ListBase *drags)
|
||||
{
|
||||
AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_);
|
||||
std::unique_ptr<AbstractTreeViewItemDropController> drop_controller =
|
||||
item.create_drop_controller();
|
||||
|
||||
const char *disabled_hint_dummy = nullptr;
|
||||
LISTBASE_FOREACH (const wmDrag *, drag, drags) {
|
||||
if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) {
|
||||
return drop_controller->on_drop(C, *drag);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_);
|
||||
return TreeViewItemAPIWrapper::drop_handle(*C, item, *drags);
|
||||
}
|
||||
|
||||
bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle)
|
||||
{
|
||||
const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle);
|
||||
const AbstractTreeView &tree_view = item.get_tree_view();
|
||||
return !tree_view.is_renaming() && item.can_rename();
|
||||
return TreeViewItemAPIWrapper::can_rename(item);
|
||||
}
|
||||
|
||||
void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle)
|
||||
|
|
|
@ -76,7 +76,7 @@ class AssetCatalogTreeView : public ui::AbstractTreeView {
|
|||
void activate_catalog_by_id(CatalogID catalog_id);
|
||||
|
||||
private:
|
||||
ui::BasicTreeViewItem &build_catalog_items_recursive(ui::TreeViewItemContainer &view_parent_item,
|
||||
ui::BasicTreeViewItem &build_catalog_items_recursive(ui::TreeViewOrItem &view_parent_item,
|
||||
AssetCatalogTreeItem &catalog);
|
||||
|
||||
AssetCatalogTreeViewAllItem &add_all_item();
|
||||
|
@ -98,7 +98,7 @@ class AssetCatalogTreeViewItem : public ui::BasicTreeViewItem {
|
|||
void build_row(uiLayout &row) override;
|
||||
void build_context_menu(bContext &C, uiLayout &column) const override;
|
||||
|
||||
bool can_rename() const override;
|
||||
bool supports_renaming() const override;
|
||||
bool rename(StringRefNull new_name) override;
|
||||
|
||||
/** Add drag support for catalog items. */
|
||||
|
@ -211,7 +211,7 @@ void AssetCatalogTreeView::build_tree()
|
|||
}
|
||||
|
||||
ui::BasicTreeViewItem &AssetCatalogTreeView::build_catalog_items_recursive(
|
||||
ui::TreeViewItemContainer &view_parent_item, AssetCatalogTreeItem &catalog)
|
||||
ui::TreeViewOrItem &view_parent_item, AssetCatalogTreeItem &catalog)
|
||||
{
|
||||
ui::BasicTreeViewItem &view_item = view_parent_item.add_tree_item<AssetCatalogTreeViewItem>(
|
||||
&catalog);
|
||||
|
@ -333,7 +333,7 @@ void AssetCatalogTreeViewItem::build_context_menu(bContext &C, uiLayout &column)
|
|||
UI_menutype_draw(&C, mt, &column);
|
||||
}
|
||||
|
||||
bool AssetCatalogTreeViewItem::can_rename() const
|
||||
bool AssetCatalogTreeViewItem::supports_renaming() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue