Warning, file /graphics/glaxnimate/src/core/model/factory.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include <unordered_map> 0010 #include <memory> 0011 #include <type_traits> 0012 0013 #include <QMetaObject> 0014 0015 #include "app/utils/qstring_hash.hpp" 0016 0017 namespace glaxnimate::model { 0018 0019 0020 class Object; 0021 class Document; 0022 class Composition; 0023 class ShapeElement; 0024 0025 namespace detail { 0026 0027 QString naked_type_name(QString class_name); 0028 0029 inline QString naked_type_name(const QMetaObject* obj) 0030 { 0031 return naked_type_name(obj->className()); 0032 } 0033 0034 template<class T> 0035 QString naked_type_name() 0036 { 0037 return naked_type_name(&T::staticMetaObject); 0038 } 0039 0040 0041 template<class BaseType, class... Args> 0042 class InternalFactory 0043 { 0044 private: 0045 class Builder 0046 { 0047 private: 0048 class Holder 0049 { 0050 public: 0051 virtual ~Holder() = default; 0052 virtual BaseType* construct(Args... args) const = 0; 0053 }; 0054 0055 template<class Type> 0056 class ConcreteHolder : public Holder 0057 { 0058 public: 0059 BaseType* construct(Args... args) const override 0060 { 0061 return new Type(args...); 0062 } 0063 }; 0064 0065 public: 0066 template<class Type> 0067 static Builder for_type() 0068 { 0069 return std::unique_ptr<Holder>(std::make_unique<ConcreteHolder<Type>>()); 0070 } 0071 0072 0073 BaseType* construct(Args... args) const 0074 { 0075 return constructor->construct(args...); 0076 } 0077 0078 private: 0079 Builder(std::unique_ptr<Holder> constructor) 0080 : constructor(std::move(constructor)) {} 0081 0082 std::unique_ptr<Holder> constructor; 0083 }; 0084 0085 public: 0086 BaseType* build(const QString& name, Args... args) const 0087 { 0088 auto it = constructors.find(name); 0089 if ( it == constructors.end() ) 0090 return nullptr; 0091 return it->second.construct(args...); 0092 } 0093 0094 template<class T> 0095 bool register_type() 0096 { 0097 constructors.emplace(detail::naked_type_name<T>(), Builder::template for_type<T>()); 0098 return true; 0099 } 0100 0101 private: 0102 std::unordered_map<QString, Builder> constructors; 0103 }; 0104 0105 } // namespace detail 0106 0107 class Factory : public detail::InternalFactory<Object, Document*> 0108 { 0109 public: 0110 static Factory& instance() 0111 { 0112 static Factory instance; 0113 return instance; 0114 } 0115 0116 static Object* static_build(const QString& name, model::Document* doc); 0117 0118 private: 0119 ~Factory() = default; 0120 Factory() = default; 0121 Factory(const Factory&) = delete; 0122 0123 }; 0124 0125 } // namespace glaxnimate::model