Ivan Mahonin ae9154
#pragma once
Ivan Mahonin ae9154
Ivan Mahonin ae9154
#ifndef TMETAIMAGE_INCLUDED
Ivan Mahonin ae9154
#define TMETAIMAGE_INCLUDED
Ivan Mahonin ae9154
Ivan Mahonin ae9154
#include "timage.h"
Ivan Mahonin ae9154
#include "tthreadmessage.h"
Ivan Mahonin ae9154
#include "tsmartpointer.h"
Ivan Mahonin ae9154
#include "tvariant.h"
Ivan Mahonin 57d357
#include "tconstwrapper.h"
Ivan Mahonin ae9154
Ivan Mahonin 4da757
#include <QString>
Ivan Mahonin ae9154
#include <QReadLocker>
Ivan Mahonin ae9154
#include <QWriteLocker>
Ivan Mahonin ae9154
#include <QReadWriteLock>
Ivan Mahonin ae9154
Ivan Mahonin ae9154
#include <string>
Ivan Mahonin ae9154
Ivan Mahonin ae9154
#undef DVAPI
Ivan Mahonin ae9154
#undef DVVAR
Ivan Mahonin ae9154
#ifdef TMETAIMAGE_EXPORTS
Ivan Mahonin ae9154
#define DVAPI DV_EXPORT_API
Ivan Mahonin ae9154
#define DVVAR DV_EXPORT_VAR
Ivan Mahonin ae9154
#else
Ivan Mahonin ae9154
#define DVAPI DV_IMPORT_API
Ivan Mahonin ae9154
#define DVVAR DV_IMPORT_VAR
Ivan Mahonin ae9154
#endif
Ivan Mahonin ae9154
Ivan Mahonin ae9154
//-------------------------------------------------------------------
Ivan Mahonin ae9154
Ivan Mahonin ae9154
class TMetaObject;
Ivan Mahonin ae9154
class TMetaObjectHandler;
Ivan Mahonin 57d357
typedef TSmartPointerT<TMetaObject> TMetaObjectP;  //!< smart pointer to TMetaObject
Ivan Mahonin 57d357
typedef TMetaObjectP::Holder        TMetaObjectH;  //!< smart holder of TMetaObject
Ivan Mahonin 57d357
typedef TMetaObjectP::Const         TMetaObjectPC; //!< smart pointer to constant TMetaObject
Ivan Mahonin 57d357
typedef std::vector<TMetaObjectP> TMetaObjectList;
Ivan Mahonin 57d357
typedef TConstArrayWrapperT<TMetaObjectPC, TMetaObjectP> TMetaObjectListCW; // TMetaObjectListConstWrapper
Ivan Mahonin ae9154
Ivan Mahonin ae9154
//-------------------------------------------------------------------
Ivan Mahonin ae9154
Ivan Mahonin 4da757
class DVAPI TMetaObjectType {
Ivan Mahonin 4da757
public:
Ivan Mahonin 4da757
  const TStringId name;
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  TMetaObjectType(const TStringId &name);
Ivan Mahonin 4da757
  virtual ~TMetaObjectType();
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  void registerAlias(const TStringId &alias);
Ivan Mahonin 4da757
  void unregisterAlias(const TStringId &alias);
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  virtual TMetaObjectHandler* createHandler(TMetaObject &obj) const
Ivan Mahonin 4da757
    { return 0; }
Ivan Mahonin 4da757
  virtual QString getLocalName() const
Ivan Mahonin 4da757
    { return QString::fromStdString(name.str()); }
Ivan Mahonin 4da757
};
Ivan Mahonin 4da757
Ivan Mahonin 4da757
//-------------------------------------------------------------------
Ivan Mahonin 4da757
Ivan Mahonin ae9154
class DVAPI TMetaObject: public TSmartObject, public TVariantOwner {
Ivan Mahonin ae9154
public:
Ivan Mahonin 249386
  typedef TMetaObjectHandler* (*Fabric)(TMetaObject&);
Ivan Mahonin 4da757
  typedef std::map<TStringId, const TMetaObjectType*> Registry;
Ivan Mahonin ae9154
Ivan Mahonin 4da757
  struct LinkedList {
Ivan Mahonin 4da757
    TMetaObject *first, *last;
Ivan Mahonin 4da757
    LinkedList(): first(), last() { }
Ivan Mahonin ae9154
  };
Ivan Mahonin 4da757
  typedef std::map<TStringId, LinkedList> LinkedMap;
Ivan Mahonin 4da757
  typedef LinkedMap::iterator LinkedMapEntry;
Ivan Mahonin ae9154
Ivan Mahonin ae9154
private:
Ivan Mahonin 4da757
  LinkedMapEntry m_typeLink;
Ivan Mahonin 4da757
  TMetaObject *m_previous, *m_next;
Ivan Mahonin 4da757
  const TMetaObjectType *m_typeDesc;
Ivan Mahonin ae9154
  TMetaObjectHandler *m_handler;
Ivan Mahonin ae9154
  TVariant m_data;
Ivan Mahonin ae9154
Ivan Mahonin 4da757
  static Registry& registry();
Ivan Mahonin 4da757
  static LinkedMap& linkedMap();
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  static void rewrapAll(const TStringId &type);
Ivan Mahonin 4da757
  void rewrap(const TStringId &type);
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  void linkToType(const TStringId &type);
Ivan Mahonin 4da757
  void unlinkFromType();
Ivan Mahonin 4da757
Ivan Mahonin 57d357
  TMetaObject(const TMetaObject &other);
Ivan Mahonin 57d357
Ivan Mahonin ae9154
public:
Ivan Mahonin 57d357
  explicit TMetaObject(const TStringId &typeName = TStringId(), const TVariant &data = TVariant());
Ivan Mahonin 57d357
  explicit TMetaObject(const std::string &typeName, const TVariant &data = TVariant());
Ivan Mahonin ae9154
  ~TMetaObject();
Ivan Mahonin ae9154
Ivan Mahonin ae9154
  void setType(const TStringId &name);
Ivan Mahonin ae9154
  inline void setType(const std::string &name)
Ivan Mahonin ae9154
    { setType(TStringId(name)); }
Ivan Mahonin ae9154
  inline void resetType()
Ivan Mahonin ae9154
    { setType(TStringId()); }
Ivan Mahonin 4da757
Ivan Mahonin 4da757
  inline const TMetaObjectType* getTypeDesc() const
Ivan Mahonin 4da757
    { return m_typeDesc; }
Ivan Mahonin ae9154
  inline const TStringId& getType() const
Ivan Mahonin 4da757
    { return m_typeLink->first; }
Ivan Mahonin ae9154
  inline const std::string& getTypeName() const
Ivan Mahonin 4da757
    { return getType().str(); }
Ivan Mahonin ae9154
  inline const TVariant& data() const
Ivan Mahonin ae9154
    { return m_data; }
Ivan Mahonin ae9154
  inline TVariant& data()
Ivan Mahonin ae9154
    { return m_data; }
Ivan Mahonin ae9154
Ivan Mahonin 57d357
  void setDefaults();
Ivan Mahonin 57d357
Ivan Mahonin ae9154
  template<typename T>
Ivan Mahonin ae9154
  const T* getHandler() const
Ivan Mahonin 249386
    { return dynamic_cast<const T*>(m_handler); }
Ivan Mahonin ae9154
  template<typename T>
Ivan Mahonin ae9154
  T* getHandler()
Ivan Mahonin ae9154
    { return dynamic_cast<T*>(m_handler); }
Ivan Mahonin ae9154
Ivan Mahonin 57d357
  TMetaObjectHandler* handler() { return m_handler; }
Ivan Mahonin 57d357
  const TMetaObjectHandler* handler() const { return m_handler; }
Ivan Mahonin 57d357
Ivan Mahonin ae9154
  void onVariantChanged(const TVariant &value) override;
Ivan Mahonin ae9154
Ivan Mahonin 57d357
  virtual TMetaObject* clone() const;
Ivan Mahonin 57d357
Ivan Mahonin 4da757
public:
Ivan Mahonin 4da757
  static const Registry& getRegistry() { return registry(); }
Ivan Mahonin 4da757
  static void registerType(const TStringId &name, const TMetaObjectType &type); //!< register new or add alias
Ivan Mahonin 4da757
  static void unregisterType(const TStringId &name); //!< unregister single alias
Ivan Mahonin 4da757
  static void unregisterType(const TMetaObjectType &type); //!< unregister all aliases
Ivan Mahonin 4da757
  static const TMetaObjectType* findType(const TStringId &name);
Ivan Mahonin ae9154
};
Ivan Mahonin ae9154
Ivan Mahonin ae9154
//-------------------------------------------------------------------
Ivan Mahonin ae9154
Ivan Mahonin ae9154
class DVAPI TMetaObjectHandler {
Ivan Mahonin 57d357
protected:
Ivan Mahonin 57d357
  class LockEvents {
Ivan Mahonin 57d357
  public:
Ivan Mahonin 57d357
    TMetaObjectHandler &owner;
Ivan Mahonin 57d357
    explicit LockEvents(TMetaObjectHandler &owner):
Ivan Mahonin 57d357
      owner(owner) { ++owner.m_locks; }
Ivan Mahonin 57d357
    ~LockEvents() { --owner.m_locks; }
Ivan Mahonin 57d357
  };
Ivan Mahonin 57d357
Ivan Mahonin ae9154
private:
Ivan Mahonin ae9154
  TMetaObject &m_object;
Ivan Mahonin 4da757
  const TMetaObjectType &m_typeDesc;
Ivan Mahonin 57d357
  TAtomicVar m_locks;
Ivan Mahonin ae9154
Ivan Mahonin ae9154
public:
Ivan Mahonin ae9154
  TMetaObjectHandler(TMetaObject &object):
Ivan Mahonin 4da757
    m_object(object),
Ivan Mahonin 4da757
    m_typeDesc(*m_object.getTypeDesc())
Ivan Mahonin 4da757
      { assert(m_object.getTypeDesc()); }
Ivan Mahonin ae9154
  virtual ~TMetaObjectHandler() { }
Ivan Mahonin ae9154
Ivan Mahonin 4da757
  inline const TMetaObjectType& getTypeDesc() const
Ivan Mahonin 4da757
    { return m_typeDesc; }
Ivan Mahonin 4da757
  inline const TStringId& getType() const
Ivan Mahonin 4da757
    { return getTypeDesc().name; }
Ivan Mahonin 4da757
  inline const std::string& getTypeName() const
Ivan Mahonin 4da757
    { return getType().str(); }
Ivan Mahonin ae9154
  inline const TMetaObject& object() const
Ivan Mahonin ae9154
    { return m_object; }
Ivan Mahonin ae9154
  inline TMetaObject& object()
Ivan Mahonin ae9154
    { return m_object; }
Ivan Mahonin 4da757
  inline const TStringId& getAlias() const
Ivan Mahonin 4da757
    { return object().getType(); }
Ivan Mahonin 4da757
  inline const std::string& getAliasName() const
Ivan Mahonin 4da757
    { return getAlias().str(); }
Ivan Mahonin ae9154
  inline const TVariant& data() const
Ivan Mahonin ae9154
    { return object().data(); }
Ivan Mahonin ae9154
  inline TVariant& data()
Ivan Mahonin ae9154
    { return object().data(); }
Ivan Mahonin ae9154
Ivan Mahonin 9cf8be
protected:
Ivan Mahonin 57d357
  virtual void onSetDefaults() { }
Ivan Mahonin ae9154
  virtual void onDataChanged(const TVariant &value) { }
Ivan Mahonin 9cf8be
  virtual void onFixData() { }
Ivan Mahonin 9cf8be
Ivan Mahonin 9cf8be
public:
Ivan Mahonin 57d357
  void setDefaults()
Ivan Mahonin 57d357
    { onSetDefaults(); }
Ivan Mahonin 9cf8be
  void dataChanged(const TVariant &value)
Ivan Mahonin 57d357
    { if (m_locks == 0) onDataChanged(value); }
Ivan Mahonin 57d357
  void fixData()
Ivan Mahonin 57d357
    { LockEvents lock(*this); onFixData(); }
Ivan Mahonin ae9154
};
Ivan Mahonin ae9154
Ivan Mahonin ae9154
//-------------------------------------------------------------------
Ivan Mahonin ae9154
Ivan Mahonin ae9154
//! An image containing an assistants for painting.
Ivan Mahonin ae9154
Ivan Mahonin ae9154
class DVAPI TMetaImage final : public TImage {
Ivan Mahonin ae9154
public:
Ivan Mahonin ae9154
  class Reader: public QReadLocker {
Ivan Mahonin ae9154
  private:
Ivan Mahonin ae9154
    const TMetaImage &m_image;
Ivan Mahonin 57d357
    const TMetaObjectListCW m_objects;
Ivan Mahonin ae9154
  public:
Ivan Mahonin ae9154
    Reader(const TMetaImage &image):
Ivan Mahonin 57d357
      QReadLocker(&image.m_rwLock),
Ivan Mahonin 57d357
      m_image(image),
Ivan Mahonin 57d357
      m_objects(image.m_objects) { }
Ivan Mahonin ae9154
    const TMetaImage& image() const
Ivan Mahonin ae9154
      { return m_image; }
Ivan Mahonin 57d357
    const TMetaObjectListCW& get() const
Ivan Mahonin 57d357
      { return m_objects; }
Ivan Mahonin 57d357
    const TMetaObjectListCW& operator*() const
Ivan Mahonin ae9154
      { return get(); }
Ivan Mahonin 57d357
    const TMetaObjectListCW* operator->() const
Ivan Mahonin ae9154
      { return &get(); }
Ivan Mahonin ae9154
  };
Ivan Mahonin ae9154
Ivan Mahonin ae9154
  class Writer: public QWriteLocker {
Ivan Mahonin ae9154
  private:
Ivan Mahonin ae9154
    TMetaImage &m_image;
Ivan Mahonin ae9154
  public:
Ivan Mahonin ae9154
    Writer(TMetaImage &image):
Ivan Mahonin ae9154
      QWriteLocker(&image.m_rwLock), m_image(image) { }
Ivan Mahonin ae9154
    TMetaImage& image() const
Ivan Mahonin ae9154
      { return m_image; }
Ivan Mahonin 57d357
    TMetaObjectList& get() const
Ivan Mahonin ae9154
      { return m_image.m_objects; }
Ivan Mahonin 57d357
    TMetaObjectList& operator*() const
Ivan Mahonin ae9154
      { return get(); }
Ivan Mahonin 57d357
    TMetaObjectList* operator->() const
Ivan Mahonin ae9154
      { return &get(); }
Ivan Mahonin ae9154
  };
Ivan Mahonin ae9154
Ivan Mahonin ae9154
private:
Ivan Mahonin ae9154
  mutable QReadWriteLock m_rwLock;
Ivan Mahonin 57d357
  TMetaObjectList m_objects;
Ivan Mahonin ae9154
Ivan Mahonin ae9154
  TMetaImage(const TMetaImage &other);
Ivan Mahonin 57d357
Ivan Mahonin 57d357
  //! not implemented
Ivan Mahonin ae9154
  TMetaImage &operator=(const TMetaImage &) { return *this; }
Ivan Mahonin ae9154
Ivan Mahonin ae9154
public:
Ivan Mahonin ae9154
  TMetaImage();
Ivan Mahonin ae9154
  ~TMetaImage();
Ivan Mahonin ae9154
Ivan Mahonin ae9154
  //! Return the image type
Ivan Mahonin ae9154
  TImage::Type getType() const override { return TImage::META; }
Ivan Mahonin ae9154
  //! Return a clone of image
Ivan Mahonin ae9154
  TImage* cloneImage() const override;
Ivan Mahonin ae9154
  //! Return the bbox of the image
Ivan Mahonin ae9154
  TRectD getBBox() const override;
Ivan Mahonin ae9154
};
Ivan Mahonin ae9154
Ivan Mahonin ae9154
#endif