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