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:
Diffstat (limited to 'source/blender/editors/interface/interface_view.cc')
-rw-r--r--source/blender/editors/interface/interface_view.cc133
1 files changed, 133 insertions, 0 deletions
diff --git a/source/blender/editors/interface/interface_view.cc b/source/blender/editors/interface/interface_view.cc
new file mode 100644
index 00000000000..b199ce9562e
--- /dev/null
+++ b/source/blender/editors/interface/interface_view.cc
@@ -0,0 +1,133 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup edinterface
+ *
+ * This part of the UI-View API is mostly needed to support persistent state of items within the
+ * view. Views are stored in #uiBlock's, and kept alive with it until after the next redraw. So we
+ * can compare the old view items with the new view items and keep state persistent for matching
+ * ones.
+ */
+
+#include <memory>
+#include <variant>
+
+#include "DNA_screen_types.h"
+
+#include "BLI_listbase.h"
+
+#include "interface_intern.h"
+
+#include "UI_interface.hh"
+#include "UI_tree_view.hh"
+
+using namespace blender;
+using namespace blender::ui;
+
+/**
+ * Wrapper to store views in a #ListBase. There's no `uiView` base class, we just store views as a
+ * #std::variant.
+ */
+struct ViewLink : public Link {
+ using TreeViewPtr = std::unique_ptr<AbstractTreeView>;
+
+ std::string idname;
+ /* Note: Can't use std::get() on this until minimum macOS deployment target is 10.14. */
+ std::variant<TreeViewPtr> view;
+};
+
+template<class T> T *get_view_from_link(ViewLink &link)
+{
+ auto *t_uptr = std::get_if<std::unique_ptr<T>>(&link.view);
+ return t_uptr ? t_uptr->get() : nullptr;
+}
+
+/**
+ * Override this for all available tree types.
+ */
+AbstractTreeView *UI_block_add_view(uiBlock &block,
+ StringRef idname,
+ std::unique_ptr<AbstractTreeView> tree_view)
+{
+ ViewLink *view_link = OBJECT_GUARDED_NEW(ViewLink);
+ BLI_addtail(&block.views, view_link);
+
+ view_link->view = std::move(tree_view);
+ view_link->idname = idname;
+
+ return get_view_from_link<AbstractTreeView>(*view_link);
+}
+
+void ui_block_free_views(uiBlock *block)
+{
+ LISTBASE_FOREACH_MUTABLE (ViewLink *, link, &block->views) {
+ OBJECT_GUARDED_DELETE(link, ViewLink);
+ }
+}
+
+/**
+ * \param x, y: Coordinate to find a tree-row item at, in window space.
+ */
+uiTreeViewItemHandle *UI_block_tree_view_find_item_at(const ARegion *region,
+ const int x,
+ const int y)
+{
+ uiButTreeRow *tree_row_but = (uiButTreeRow *)ui_tree_row_find_mouse_over(region, x, y);
+ if (!tree_row_but) {
+ return nullptr;
+ }
+
+ return tree_row_but->tree_item;
+}
+
+static StringRef ui_block_view_find_idname(const uiBlock &block, const AbstractTreeView &view)
+{
+ /* First get the idname the of the view we're looking for. */
+ LISTBASE_FOREACH (ViewLink *, view_link, &block.views) {
+ if (get_view_from_link<AbstractTreeView>(*view_link) == &view) {
+ return view_link->idname;
+ }
+ }
+
+ return {};
+}
+
+uiTreeViewHandle *ui_block_view_find_matching_in_old_block(const uiBlock *new_block,
+ const uiTreeViewHandle *new_view_handle)
+{
+ const AbstractTreeView &needle_view = reinterpret_cast<const AbstractTreeView &>(
+ *new_view_handle);
+
+ uiBlock *old_block = new_block->oldblock;
+ if (!old_block) {
+ return nullptr;
+ }
+
+ StringRef idname = ui_block_view_find_idname(*new_block, needle_view);
+ if (idname.is_empty()) {
+ return nullptr;
+ }
+
+ LISTBASE_FOREACH (ViewLink *, old_view_link, &old_block->views) {
+ if (old_view_link->idname == idname) {
+ return reinterpret_cast<uiTreeViewHandle *>(
+ get_view_from_link<AbstractTreeView>(*old_view_link));
+ }
+ }
+
+ return nullptr;
+}