ae9154
#pragma once
ae9154
ae9154
#ifndef TMETAIMAGE_INCLUDED
ae9154
#define TMETAIMAGE_INCLUDED
ae9154
ae9154
#include "timage.h"
ae9154
#include "tthreadmessage.h"
ae9154
#include "tsmartpointer.h"
ae9154
#include "tvariant.h"
ae9154
ae9154
#include <qreadlocker></qreadlocker>
ae9154
#include <qwritelocker></qwritelocker>
ae9154
#include <qreadwritelock></qreadwritelock>
ae9154
ae9154
#include <string></string>
ae9154
ae9154
#undef DVAPI
ae9154
#undef DVVAR
ae9154
#ifdef TMETAIMAGE_EXPORTS
ae9154
#define DVAPI DV_EXPORT_API
ae9154
#define DVVAR DV_EXPORT_VAR
ae9154
#else
ae9154
#define DVAPI DV_IMPORT_API
ae9154
#define DVVAR DV_IMPORT_VAR
ae9154
#endif
ae9154
ae9154
//-------------------------------------------------------------------
ae9154
ae9154
class TMetaObject;
ae9154
class TMetaObjectHandler;
ae9154
typedef TSmartPointerT<tmetaobject> TMetaObjectP;</tmetaobject>
ae9154
typedef TSmartRefT<tmetaobject> TMetaObjectR;</tmetaobject>
ae9154
typedef std::vector<tmetaobjectr> TMetaObjectRefList;</tmetaobjectr>
ae9154
ae9154
//-------------------------------------------------------------------
ae9154
ae9154
class DVAPI TMetaObject: public TSmartObject, public TVariantOwner {
ae9154
public:
249386
  typedef TMetaObjectHandler* (*Fabric)(TMetaObject&);
ae9154
  typedef std::map<tstringid, fabric=""> Registry;</tstringid,>
ae9154
ae9154
  template<typename t=""></typename>
ae9154
  class Registrator {
ae9154
  public:
ae9154
    typedef T Type;
249386
    static TMetaObjectHandler* fabric(TMetaObject &obj)
249386
      { return new Type(obj); }
ae9154
    Registrator(const std::string &typeName)
ae9154
      { registerType(typeName, fabric); }
ae9154
    Registrator(const TStringId &typeName)
ae9154
      { registerType(typeName, fabric); }
ae9154
  };
ae9154
ae9154
private:
ae9154
  TStringId m_type;
ae9154
  TMetaObjectHandler *m_handler;
ae9154
  TVariant m_data;
ae9154
ae9154
public:
ae9154
  explicit TMetaObject(const TStringId &typeName = TStringId());
ae9154
  explicit TMetaObject(const std::string &typeName);
ae9154
  ~TMetaObject();
ae9154
ae9154
  void setType(const TStringId &name);
ae9154
  inline void setType(const std::string &name)
ae9154
    { setType(TStringId(name)); }
ae9154
  inline void resetType()
ae9154
    { setType(TStringId()); }
ae9154
  inline const TStringId& getType() const
ae9154
    { return m_type; }
ae9154
  inline const std::string& getTypeName() const
ae9154
    { return m_type.str(); }
ae9154
  inline const TVariant& data() const
ae9154
    { return m_data; }
ae9154
  inline TVariant& data()
ae9154
    { return m_data; }
ae9154
ae9154
  template<typename t=""></typename>
ae9154
  const T* getHandler() const
249386
    { return dynamic_cast<const t*="">(m_handler); }</const>
ae9154
  template<typename t=""></typename>
ae9154
  T* getHandler()
ae9154
    { return dynamic_cast<t*>(m_handler); }</t*>
ae9154
ae9154
  void onVariantChanged(const TVariant &value) override;
ae9154
ae9154
  static Registry& registry();
ae9154
  static void registerType(const TStringId &name, Fabric fabric);
ae9154
  static void unregisterType(const TStringId &name);
ae9154
  inline static void registerType(const std::string &name, Fabric fabric)
ae9154
    { registerType(TStringId(name), fabric); }
ae9154
  inline static void unregisterType(const std::string &name)
ae9154
    { unregisterType(TStringId::find(name)); }
ae9154
};
ae9154
ae9154
//-------------------------------------------------------------------
ae9154
ae9154
class DVAPI TMetaObjectHandler {
ae9154
private:
ae9154
  TMetaObject &m_object;
249386
  TAtomicVar m_fixingData;
ae9154
ae9154
public:
ae9154
  TMetaObjectHandler(TMetaObject &object):
ae9154
    m_object(object) { }
ae9154
  virtual ~TMetaObjectHandler() { }
ae9154
ae9154
  inline const TMetaObject& object() const
ae9154
    { return m_object; }
ae9154
  inline TMetaObject& object()
ae9154
    { return m_object; }
ae9154
  inline const TVariant& data() const
ae9154
    { return object().data(); }
ae9154
  inline TVariant& data()
ae9154
    { return object().data(); }
ae9154
9cf8be
protected:
ae9154
  virtual void onDataChanged(const TVariant &value) { }
9cf8be
  virtual void onFixData() { }
9cf8be
9cf8be
public:
9cf8be
  void dataChanged(const TVariant &value)
249386
    { if (m_fixingData == 0) onDataChanged(value); }
9cf8be
9cf8be
  void fixData() {
249386
    ++m_fixingData;
249386
    if (m_fixingData == 1) onFixData();
249386
    --m_fixingData;
9cf8be
  }
ae9154
};
ae9154
ae9154
//-------------------------------------------------------------------
ae9154
ae9154
//! An image containing an assistants for painting.
ae9154
ae9154
class DVAPI TMetaImage final : public TImage {
ae9154
public:
ae9154
  class Reader: public QReadLocker {
ae9154
  private:
ae9154
    const TMetaImage &m_image;
ae9154
  public:
ae9154
    Reader(const TMetaImage &image):
ae9154
      QReadLocker(&image.m_rwLock), m_image(image) { }
ae9154
    const TMetaImage& image() const
ae9154
      { return m_image; }
ae9154
    const TMetaObjectRefList& get() const
ae9154
      { return m_image.m_objects; }
ae9154
    const TMetaObjectRefList& operator*() const
ae9154
      { return get(); }
ae9154
    const TMetaObjectRefList* operator->() const
ae9154
      { return &get(); }
ae9154
  };
ae9154
ae9154
  class Writer: public QWriteLocker {
ae9154
  private:
ae9154
    TMetaImage &m_image;
ae9154
  public:
ae9154
    Writer(TMetaImage &image):
ae9154
      QWriteLocker(&image.m_rwLock), m_image(image) { }
ae9154
    TMetaImage& image() const
ae9154
      { return m_image; }
ae9154
    TMetaObjectRefList& get() const
ae9154
      { return m_image.m_objects; }
ae9154
    TMetaObjectRefList& operator*() const
ae9154
      { return get(); }
ae9154
    TMetaObjectRefList* operator->() const
ae9154
      { return &get(); }
ae9154
  };
ae9154
ae9154
private:
ae9154
  mutable QReadWriteLock m_rwLock;
ae9154
  TMetaObjectRefList m_objects;
ae9154
ae9154
  //! not implemented
ae9154
  TMetaImage(const TMetaImage &other);
ae9154
  TMetaImage &operator=(const TMetaImage &) { return *this; }
ae9154
ae9154
public:
ae9154
  TMetaImage();
ae9154
  ~TMetaImage();
ae9154
ae9154
  //! Return the image type
ae9154
  TImage::Type getType() const override { return TImage::META; }
ae9154
  //! Return a clone of image
ae9154
  TImage* cloneImage() const override;
ae9154
  //! Return the bbox of the image
ae9154
  TRectD getBBox() const override;
ae9154
};
ae9154
ae9154
#endif