process_node.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* process_node.h - node processor
  2. * Copyright (C) 2017-2018 caryoscelus
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. */
  17. #ifndef STUDIO_ACTIONS_PROCESS_NODE_H_D9E2969B_5C37_5085_828C_4708ED7EC469
  18. #define STUDIO_ACTIONS_PROCESS_NODE_H_D9E2969B_5C37_5085_828C_4708ED7EC469
  19. #include <core/util/class_init.h>
  20. #include <core/abstract_factory.h>
  21. #include <generic/context_listener.h>
  22. namespace rainynite::studio {
  23. template <typename T, typename Tag>
  24. class ProcessNode : public ContextListener {
  25. public:
  26. virtual bool accept(core::NodeTreeIndex index) const = 0;
  27. virtual void feed(T const& argument) = 0;
  28. virtual void start_list() {}
  29. virtual void end_list() {}
  30. bool set_node(core::NodeTreeIndex index_) {
  31. if (accept(index_)) {
  32. index = index_;
  33. return true;
  34. }
  35. return false;
  36. }
  37. core::NodeTreeIndex get_node_index() const {
  38. return index;
  39. }
  40. shared_ptr<core::AbstractValue> get_node() const {
  41. return get_context()->tree()->get_node(index);
  42. }
  43. private:
  44. core::NodeTreeIndex index;
  45. };
  46. template <class P, typename Base>
  47. struct ProcessNodeFactoryImpl :
  48. public AbstractFactoryImpl<Base, P>,
  49. private class_init::ListRegistered<
  50. ProcessNodeFactoryImpl<P, Base>,
  51. AbstractFactory<Base>
  52. >
  53. {};
  54. #define REGISTER_PROCESS_NODE(Processor, Base) \
  55. template struct ProcessNodeFactoryImpl<Processor, Base>;
  56. template <typename Processor>
  57. class FindTargetNode {
  58. public:
  59. unique_ptr<Processor> find_appropriate_target(core::NodeTree const& tree, shared_ptr<EditorContext> ctx) {
  60. if (auto node = ctx->get_active_node_index()) {
  61. if (auto r = check_target(node, ctx))
  62. return r;
  63. for (size_t i = 0; i < tree.children_count(node); ++i) {
  64. if (auto r = check_target(tree.index(node, i), ctx))
  65. return r;
  66. }
  67. }
  68. auto doc_root = tree.get_root_index();
  69. for (size_t i = 0; i < tree.children_count(doc_root); ++i) {
  70. if (auto r = check_target(tree.index(doc_root, i), ctx))
  71. return r;
  72. }
  73. core::NodeTreeIndex root;
  74. try {
  75. root = index_of_property(tree, doc_root, "root");
  76. } catch (...) {
  77. return nullptr;
  78. }
  79. for (size_t i = 0; i < tree.children_count(root); ++i) {
  80. if (auto r = check_target(tree.index(root, i), ctx))
  81. return r;
  82. }
  83. return {};
  84. }
  85. unique_ptr<Processor> check_target(core::NodeTreeIndex node, shared_ptr<EditorContext> ctx) const {
  86. using namespace class_init;
  87. for (auto factory : class_list_registry<AbstractFactory<Processor>>()) {
  88. auto r = (*factory)();
  89. r->set_context(ctx);
  90. if (r->set_node(node))
  91. return r;
  92. }
  93. return nullptr;
  94. }
  95. };
  96. } // namespace rainynite::studio
  97. #endif