Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/interface/tree_view.cc
| Show All 33 Lines | |||||
| #include "UI_tree_view.hh" | #include "UI_tree_view.hh" | ||||
| namespace blender::ui { | namespace blender::ui { | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| /** | /** | ||||
| * Add a tree-item to the container. This is the only place where items should be added, it handles | * Add a tree-item to the container. This is the only place where items should be added, it | ||||
| * important invariants! | * handles important invariants! | ||||
| */ | */ | ||||
| AbstractTreeViewItem &TreeViewItemContainer::add_tree_item( | AbstractTreeViewItem &TreeViewItemContainer::add_tree_item( | ||||
| std::unique_ptr<AbstractTreeViewItem> item) | std::unique_ptr<AbstractTreeViewItem> item) | ||||
| { | { | ||||
| children_.append(std::move(item)); | children_.append(std::move(item)); | ||||
| /* The first item that will be added to the root sets this. */ | /* The first item that will be added to the root sets this. */ | ||||
| if (root_ == nullptr) { | if (root_ == nullptr) { | ||||
| Show All 30 Lines | void AbstractTreeView::foreach_item(ItemIterFn iter_fn, IterOptions options) const | ||||
| foreach_item_recursive(iter_fn, options); | foreach_item_recursive(iter_fn, options); | ||||
| } | } | ||||
| bool AbstractTreeView::is_renaming() const | bool AbstractTreeView::is_renaming() const | ||||
| { | { | ||||
| return rename_buffer_ != nullptr; | 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) | void AbstractTreeView::update_from_old(uiBlock &new_block) | ||||
| { | { | ||||
| uiBlock *old_block = new_block.oldblock; | uiBlock *old_block = new_block.oldblock; | ||||
| if (!old_block) { | if (!old_block) { | ||||
| /* Initial construction, nothing to update. */ | /* Initial construction, nothing to update. */ | ||||
| is_reconstructed_ = true; | is_reconstructed_ = true; | ||||
| return; | return; | ||||
| } | } | ||||
| Show All 14 Lines | void AbstractTreeView::update_from_old(uiBlock &new_block) | ||||
| old_view.rename_buffer_ = nullptr; | old_view.rename_buffer_ = nullptr; | ||||
| update_children_from_old_recursive(*this, old_view); | update_children_from_old_recursive(*this, old_view); | ||||
| /* Finished (re-)constructing the tree. */ | /* Finished (re-)constructing the tree. */ | ||||
| is_reconstructed_ = true; | is_reconstructed_ = true; | ||||
| } | } | ||||
| void AbstractTreeView::update_children_from_old_recursive(const TreeViewItemContainer &new_items, | void AbstractTreeView::update_children_from_old_recursive(const TreeViewOrItem &new_items, | ||||
| const TreeViewItemContainer &old_items) | const TreeViewOrItem &old_items) | ||||
| { | { | ||||
| for (const auto &new_item : new_items.children_) { | for (const auto &new_item : new_items.children_) { | ||||
| AbstractTreeViewItem *matching_old_item = find_matching_child(*new_item, old_items); | AbstractTreeViewItem *matching_old_item = find_matching_child(*new_item, old_items); | ||||
| if (!matching_old_item) { | if (!matching_old_item) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| new_item->update_from_old(*matching_old_item); | new_item->update_from_old(*matching_old_item); | ||||
| /* Recurse into children of the matched item. */ | /* Recurse into children of the matched item. */ | ||||
| update_children_from_old_recursive(*new_item, *matching_old_item); | update_children_from_old_recursive(*new_item, *matching_old_item); | ||||
| } | } | ||||
| } | } | ||||
| AbstractTreeViewItem *AbstractTreeView::find_matching_child( | 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_) { | for (const auto &iter_item : items.children_) { | ||||
| if (lookup_item.matches(*iter_item)) { | if (lookup_item.matches(*iter_item)) { | ||||
| /* We have a matching item! */ | /* We have a matching item! */ | ||||
| return iter_item.get(); | return iter_item.get(); | ||||
| } | } | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | |||||
| std::unique_ptr<AbstractTreeViewItemDropController> AbstractTreeViewItem::create_drop_controller() | std::unique_ptr<AbstractTreeViewItemDropController> AbstractTreeViewItem::create_drop_controller() | ||||
| const | const | ||||
| { | { | ||||
| /* There's no drop controller (and hence no drop support) by default. */ | /* There's no drop controller (and hence no drop support) by default. */ | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| bool AbstractTreeViewItem::can_rename() const | bool AbstractTreeViewItem::supports_renaming() const | ||||
| { | { | ||||
| /* No renaming by default. */ | /* No renaming by default. */ | ||||
| return false; | return false; | ||||
| } | } | ||||
| bool AbstractTreeViewItem::rename(StringRefNull new_name) | bool AbstractTreeViewItem::rename(StringRefNull new_name) | ||||
| { | { | ||||
| /* It is important to update the label after renaming, so #AbstractTreeViewItem::matches() | /* It is important to update the label after renaming, so #AbstractTreeViewItem::matches() | ||||
| Show All 17 Lines | |||||
| bool AbstractTreeViewItem::matches(const AbstractTreeViewItem &other) const | bool AbstractTreeViewItem::matches(const AbstractTreeViewItem &other) const | ||||
| { | { | ||||
| return label_ == other.label_; | return label_ == other.label_; | ||||
| } | } | ||||
| void AbstractTreeViewItem::begin_renaming() | void AbstractTreeViewItem::begin_renaming() | ||||
| { | { | ||||
| AbstractTreeView &tree_view = get_tree_view(); | AbstractTreeView &tree_view = get_tree_view(); | ||||
| if (tree_view.is_renaming() || !can_rename()) { | if (tree_view.is_renaming() || !supports_renaming()) { | ||||
| return; | return; | ||||
| } | } | ||||
| is_renaming_ = true; | is_renaming_ = true; | ||||
| tree_view.rename_buffer_ = std::make_unique<decltype(tree_view.rename_buffer_)::element_type>(); | tree_view.rename_buffer_ = std::make_unique<decltype(tree_view.rename_buffer_)::element_type>(); | ||||
| std::copy(std::begin(label_), std::end(label_), std::begin(*tree_view.rename_buffer_)); | std::copy(std::begin(label_), std::end(label_), std::begin(*tree_view.rename_buffer_)); | ||||
| } | } | ||||
| Show All 13 Lines | |||||
| AbstractTreeView &AbstractTreeViewItem::get_tree_view() const | AbstractTreeView &AbstractTreeViewItem::get_tree_view() const | ||||
| { | { | ||||
| return static_cast<AbstractTreeView &>(*root_); | return static_cast<AbstractTreeView &>(*root_); | ||||
| } | } | ||||
| int AbstractTreeViewItem::count_parents() const | int AbstractTreeViewItem::count_parents() const | ||||
| { | { | ||||
| int i = 0; | int i = 0; | ||||
| for (TreeViewItemContainer *parent = parent_; parent; parent = parent->parent_) { | for (AbstractTreeViewItem *parent = parent_; parent; parent = parent->parent_) { | ||||
| i++; | i++; | ||||
| } | } | ||||
| return i; | return i; | ||||
| } | } | ||||
| void AbstractTreeViewItem::activate() | void AbstractTreeViewItem::activate() | ||||
| { | { | ||||
| BLI_assert_msg(get_tree_view().is_reconstructed(), | BLI_assert_msg(get_tree_view().is_reconstructed(), | ||||
| ▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | |||||
| AbstractTreeViewItemDropController::AbstractTreeViewItemDropController(AbstractTreeView &tree_view) | AbstractTreeViewItemDropController::AbstractTreeViewItemDropController(AbstractTreeView &tree_view) | ||||
| : tree_view_(tree_view) | : tree_view_(tree_view) | ||||
| { | { | ||||
| } | } | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| TreeViewBuilder::TreeViewBuilder(uiBlock &block) : block_(block) | class TreeViewLayoutBuilder { | ||||
| uiBlock &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 TreeViewBuilder::build_tree_view(AbstractTreeView &tree_view) | void TreeViewLayoutBuilder::build_from_tree(const AbstractTreeView &tree_view) | ||||
| { | { | ||||
| tree_view.build_tree(); | uiLayout *prev_layout = current_layout(); | ||||
| tree_view.update_from_old(block_); | |||||
| tree_view.change_state_delayed(); | |||||
| tree_view.build_layout_from_tree(TreeViewLayoutBuilder(block_)); | |||||
| } | |||||
| /* ---------------------------------------------------------------------- */ | uiLayout *box = uiLayoutBox(prev_layout); | ||||
| uiLayoutColumn(box, false); | |||||
| TreeViewLayoutBuilder::TreeViewLayoutBuilder(uiBlock &block) : block_(block) | tree_view.foreach_item([this](AbstractTreeViewItem &item) { build_row(item); }, | ||||
| { | AbstractTreeView::IterOptions::SkipCollapsed); | ||||
| UI_block_layout_set_current(&block(), prev_layout); | |||||
| } | } | ||||
| /** | |||||
| * 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. | |||||
| */ | |||||
| void TreeViewLayoutBuilder::polish_layout(const uiBlock &block) | void TreeViewLayoutBuilder::polish_layout(const uiBlock &block) | ||||
| { | { | ||||
| LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block.buttons) { | LISTBASE_FOREACH_BACKWARD (uiBut *, but, &block.buttons) { | ||||
| if (AbstractTreeViewItem::is_collapse_chevron_but(but) && but->next && | if (AbstractTreeViewItem::is_collapse_chevron_but(but) && but->next && | ||||
| /* Embossed buttons with padding-less text padding look weird, so don't touch them. */ | /* Embossed buttons with padding-less text padding look weird, so don't touch them. */ | ||||
| ELEM(but->next->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { | ELEM(but->next->emboss, UI_EMBOSS_NONE, UI_EMBOSS_NONE_OR_STATUS)) { | ||||
| UI_but_drawflag_enable(static_cast<uiBut *>(but->next), UI_BUT_NO_TEXT_PADDING); | UI_but_drawflag_enable(static_cast<uiBut *>(but->next), UI_BUT_NO_TEXT_PADDING); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | |||||
| uiLayout *TreeViewLayoutBuilder::current_layout() const | uiLayout *TreeViewLayoutBuilder::current_layout() const | ||||
| { | { | ||||
| return block().curlayout; | return block().curlayout; | ||||
| } | } | ||||
| /* ---------------------------------------------------------------------- */ | /* ---------------------------------------------------------------------- */ | ||||
| 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_) | BasicTreeViewItem::BasicTreeViewItem(StringRef label, BIFIconID icon_) : icon(icon_) | ||||
| { | { | ||||
| label_ = label; | label_ = label; | ||||
| } | } | ||||
| void BasicTreeViewItem::build_row(uiLayout &row) | void BasicTreeViewItem::build_row(uiLayout &row) | ||||
| { | { | ||||
| add_label(row); | add_label(row); | ||||
| Show All 30 Lines | |||||
| std::optional<bool> BasicTreeViewItem::should_be_active() const | std::optional<bool> BasicTreeViewItem::should_be_active() const | ||||
| { | { | ||||
| if (is_active_fn_) { | if (is_active_fn_) { | ||||
| return is_active_fn_(); | return is_active_fn_(); | ||||
| } | } | ||||
| return std::nullopt; | return std::nullopt; | ||||
| } | } | ||||
| } // namespace blender::ui | /* ---------------------------------------------------------------------- */ | ||||
| using namespace blender::ui; | |||||
| bool UI_tree_view_item_is_active(const uiTreeViewItemHandle *item_handle) | |||||
| { | |||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | |||||
| return item.is_active(); | |||||
| } | |||||
| bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle, | /** | ||||
| const uiTreeViewItemHandle *b_handle) | * 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) | |||||
| { | { | ||||
| 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. */ | /* TODO should match the tree-view as well. */ | ||||
| return a.matches_including_parents(b); | return a.matches_including_parents(b); | ||||
| } | } | ||||
| /** | static bool drag_start(bContext &C, const AbstractTreeViewItem &item) | ||||
| * Attempt to start dragging the tree-item \a item_. This will not work if the tree item doesn't | |||||
| * support dragging, i.e. it won't create a drag-controller upon request. | |||||
| * \return True if dragging started successfully, otherwise false. | |||||
| */ | |||||
| 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 = | const std::unique_ptr<AbstractTreeViewItemDragController> drag_controller = | ||||
| item.create_drag_controller(); | item.create_drag_controller(); | ||||
| if (!drag_controller) { | if (!drag_controller) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| WM_event_start_drag(C, | WM_event_start_drag(&C, | ||||
| ICON_NONE, | ICON_NONE, | ||||
| drag_controller->get_drag_type(), | drag_controller->get_drag_type(), | ||||
| drag_controller->create_drag_data(), | drag_controller->create_drag_data(), | ||||
| 0, | 0, | ||||
| WM_DRAG_FREE_DATA); | WM_DRAG_FREE_DATA); | ||||
| drag_controller->on_drag_start(); | drag_controller->on_drag_start(); | ||||
| return true; | return true; | ||||
| } | } | ||||
| bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, | static bool can_drop(const AbstractTreeViewItem &item, | ||||
| const wmDrag *drag, | const wmDrag &drag, | ||||
| const char **r_disabled_hint) | const char **r_disabled_hint) | ||||
| { | { | ||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_); | |||||
| const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | ||||
| item.create_drop_controller(); | item.create_drop_controller(); | ||||
| if (!drop_controller) { | if (!drop_controller) { | ||||
| return false; | return false; | ||||
| } | } | ||||
| return drop_controller->can_drop(*drag, r_disabled_hint); | return drop_controller->can_drop(drag, r_disabled_hint); | ||||
| } | } | ||||
| char *UI_tree_view_item_drop_tooltip(const uiTreeViewItemHandle *item_, const wmDrag *drag) | static std::string drop_tooltip(const AbstractTreeViewItem &item, const wmDrag &drag) | ||||
| { | { | ||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_); | |||||
| const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | const std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | ||||
| item.create_drop_controller(); | item.create_drop_controller(); | ||||
| if (!drop_controller) { | if (!drop_controller) { | ||||
| return nullptr; | return {}; | ||||
| } | } | ||||
| return BLI_strdup(drop_controller->drop_tooltip(*drag).c_str()); | return drop_controller->drop_tooltip(drag); | ||||
| } | } | ||||
| /** | static bool drop_handle(bContext &C, const AbstractTreeViewItem &item, const ListBase &drags) | ||||
| * Let a tree-view item handle a drop event. | |||||
| * \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 ListBase *drags) | |||||
| { | { | ||||
| AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_); | |||||
| std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | std::unique_ptr<AbstractTreeViewItemDropController> drop_controller = | ||||
| item.create_drop_controller(); | item.create_drop_controller(); | ||||
| const char *disabled_hint_dummy = nullptr; | const char *disabled_hint_dummy = nullptr; | ||||
| LISTBASE_FOREACH (const wmDrag *, drag, drags) { | LISTBASE_FOREACH (const wmDrag *, drag, &drags) { | ||||
| if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) { | if (drop_controller->can_drop(*drag, &disabled_hint_dummy)) { | ||||
| return drop_controller->on_drop(C, *drag); | return drop_controller->on_drop(&C, *drag); | ||||
| } | } | ||||
| } | } | ||||
| return false; | return false; | ||||
| } | } | ||||
| /** | static bool can_rename(const AbstractTreeViewItem &item) | ||||
| * Can \a item_handle be renamed right now? Not that this isn't just a mere wrapper around | { | ||||
| * #AbstractTreeViewItem::can_rename(). This also checks if there is another item being renamed, | const AbstractTreeView &tree_view = item.get_tree_view(); | ||||
| * and returns false if so. | 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) | |||||
| { | |||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | |||||
| return item.is_active(); | |||||
| } | |||||
| bool UI_tree_view_item_matches(const uiTreeViewItemHandle *a_handle, | |||||
| const uiTreeViewItemHandle *b_handle) | |||||
| { | |||||
| const AbstractTreeViewItem &a = reinterpret_cast<const AbstractTreeViewItem &>(*a_handle); | |||||
| const AbstractTreeViewItem &b = reinterpret_cast<const AbstractTreeViewItem &>(*b_handle); | |||||
| return TreeViewItemAPIWrapper::matches(a, b); | |||||
| } | |||||
| bool UI_tree_view_item_drag_start(bContext *C, uiTreeViewItemHandle *item_) | |||||
| { | |||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_); | |||||
| return TreeViewItemAPIWrapper::drag_start(*C, item); | |||||
| } | |||||
| bool UI_tree_view_item_can_drop(const uiTreeViewItemHandle *item_, | |||||
| const wmDrag *drag, | |||||
| const char **r_disabled_hint) | |||||
| { | |||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_); | |||||
| 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::string tooltip = TreeViewItemAPIWrapper::drop_tooltip(item, *drag); | |||||
| return tooltip.empty() ? nullptr : BLI_strdup(tooltip.c_str()); | |||||
| } | |||||
| bool UI_tree_view_item_drop_handle(bContext *C, | |||||
| const uiTreeViewItemHandle *item_, | |||||
| const ListBase *drags) | |||||
| { | |||||
| 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) | bool UI_tree_view_item_can_rename(const uiTreeViewItemHandle *item_handle) | ||||
| { | { | ||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | ||||
| const AbstractTreeView &tree_view = item.get_tree_view(); | return TreeViewItemAPIWrapper::can_rename(item); | ||||
| return !tree_view.is_renaming() && item.can_rename(); | |||||
| } | } | ||||
| void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle) | void UI_tree_view_item_begin_rename(uiTreeViewItemHandle *item_handle) | ||||
| { | { | ||||
| AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_handle); | AbstractTreeViewItem &item = reinterpret_cast<AbstractTreeViewItem &>(*item_handle); | ||||
| item.begin_renaming(); | item.begin_renaming(); | ||||
| } | } | ||||
| void UI_tree_view_item_context_menu_build(bContext *C, | void UI_tree_view_item_context_menu_build(bContext *C, | ||||
| const uiTreeViewItemHandle *item_handle, | const uiTreeViewItemHandle *item_handle, | ||||
| uiLayout *column) | uiLayout *column) | ||||
| { | { | ||||
| const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | const AbstractTreeViewItem &item = reinterpret_cast<const AbstractTreeViewItem &>(*item_handle); | ||||
| item.build_context_menu(*C, *column); | item.build_context_menu(*C, *column); | ||||
| } | } | ||||