Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddhartha Jejurkar <f20180617@goa.bits-pilani.ac.in>2021-12-17 16:01:32 +0300
committerSiddhartha Jejurkar <f20180617@goa.bits-pilani.ac.in>2021-12-17 16:01:32 +0300
commitdbc41b30f88b96f7d8c6e995b17f5930eb55cc77 (patch)
treec6c495328443ea3621e5df2ef483b0e0dd504496 /source/blender/editors/include/UI_tree_view.hh
parent99a2af76d10e05a18987be5d554ada197b1ca086 (diff)
parent7c9e4099854a4fc8eab4db97173c1aacd25f9e08 (diff)
Merge branch 'master' into soc-2021-uv-edge-select-supportsoc-2021-uv-edge-select-support
Diffstat (limited to 'source/blender/editors/include/UI_tree_view.hh')
-rw-r--r--source/blender/editors/include/UI_tree_view.hh195
1 files changed, 107 insertions, 88 deletions
diff --git a/source/blender/editors/include/UI_tree_view.hh b/source/blender/editors/include/UI_tree_view.hh
index 0d18eedeac9..8208f8daf5d 100644
--- a/source/blender/editors/include/UI_tree_view.hh
+++ b/source/blender/editors/include/UI_tree_view.hh
@@ -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,37 +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);
-
- 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;
/** \} */
@@ -151,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
@@ -169,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
@@ -185,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
@@ -196,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);
};
/** \} */
@@ -215,21 +190,18 @@ class AbstractTreeView : public TreeViewItemContainer {
class AbstractTreeViewItem : public TreeViewItemContainer {
friend class AbstractTreeView;
friend class TreeViewLayoutBuilder;
-
- public:
- using IsActiveFn = std::function<bool()>;
+ /* Higher-level API. */
+ friend class TreeViewItemAPIWrapper;
private:
bool is_open_ = false;
bool is_active_ = false;
bool is_renaming_ = false;
- IsActiveFn is_active_fn_;
-
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:
@@ -238,33 +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();
/**
- * Set a custom callback to check if this item should be active. There's a version without
- * arguments for checking if the item is currently in an active state.
+ * 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 void is_active(IsActiveFn is_active_fn);
+ 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.
@@ -288,47 +286,28 @@ 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.
+ * 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).
+ * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise the
+ * actual item state is unknown, possibly calling state-change update functions incorrectly.
*/
- bool is_active() const;
+ void activate();
+ void deactivate();
+
/**
* 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).
- * Requires the tree to have completed reconstruction, see #is_reconstructed(). Otherwise the
- * actual item state is unknown, possibly calling state-change update functions incorrectly.
- */
- void activate();
-
private:
static void rename_button_fn(bContext *, void *, char *);
static AbstractTreeViewItem *find_tree_item_from_rename_button(const uiBut &but);
@@ -338,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;
};
/** \} */
@@ -358,11 +340,18 @@ class AbstractTreeViewItem : public TreeViewItemContainer {
* custom implementation of #AbstractTreeViewItem::create_drag_controller().
*/
class AbstractTreeViewItemDragController {
+ protected:
+ AbstractTreeView &tree_view_;
+
public:
+ AbstractTreeViewItemDragController(AbstractTreeView &tree_view);
virtual ~AbstractTreeViewItemDragController() = default;
virtual int get_drag_type() const = 0;
virtual void *create_drag_data() const = 0;
+ virtual void on_drag_start();
+
+ template<class TreeViewType> inline TreeViewType &tree_view() const;
};
/**
@@ -398,7 +387,7 @@ class AbstractTreeViewItemDropController {
* Execute the logic to apply a drop of the data dragged with \a drag onto/into the item this
* controller is for.
*/
- virtual bool on_drop(const wmDrag &drag) = 0;
+ virtual bool on_drop(struct bContext *C, const wmDrag &drag) = 0;
template<class TreeViewType> inline TreeViewType &tree_view() const;
};
@@ -416,6 +405,7 @@ class AbstractTreeViewItemDropController {
*/
class BasicTreeViewItem : public AbstractTreeViewItem {
public:
+ using IsActiveFn = std::function<bool()>;
using ActivateFn = std::function<void(BasicTreeViewItem &new_active)>;
BIFIconID icon;
@@ -423,7 +413,11 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
void build_row(uiLayout &row) override;
void add_label(uiLayout &layout, StringRefNull label_override = "");
- void on_activate(ActivateFn fn);
+ void set_on_activate_fn(ActivateFn fn);
+ /**
+ * Set a custom callback to check if this item should be active.
+ */
+ void set_is_active_fn(IsActiveFn fn);
protected:
/**
@@ -433,15 +427,33 @@ class BasicTreeViewItem : public AbstractTreeViewItem {
*/
ActivateFn activate_fn_;
+ IsActiveFn is_active_fn_;
+
private:
static void tree_row_click_fn(struct bContext *C, void *arg1, void *arg2);
+ std::optional<bool> should_be_active() const override;
void on_activate() override;
};
/** \} */
/* ---------------------------------------------------------------------- */
+/** \name Tree-View Builder
+ * \{ */
+
+class TreeViewBuilder {
+ uiBlock &block_;
+
+ public:
+ TreeViewBuilder(uiBlock &block);
+
+ void build_tree_view(AbstractTreeView &tree_view);
+};
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
template<class ItemT, typename... Args>
inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args)
@@ -453,6 +465,13 @@ inline ItemT &TreeViewItemContainer::add_tree_item(Args &&...args)
add_tree_item(std::make_unique<ItemT>(std::forward<Args>(args)...)));
}
+template<class TreeViewType> TreeViewType &AbstractTreeViewItemDragController::tree_view() const
+{
+ static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value,
+ "Type must derive from and implement the AbstractTreeView interface");
+ return static_cast<TreeViewType &>(tree_view_);
+}
+
template<class TreeViewType> TreeViewType &AbstractTreeViewItemDropController::tree_view() const
{
static_assert(std::is_base_of<AbstractTreeView, TreeViewType>::value,