#ifndef __ACMDEF_H
#define __ACMDEF_H

#ifndef __ACM_H
	#error include 'acm.h' before including this file
#endif

/////////////////////////////////////////////////////////////////////
// (C) Copyright 1993-2005 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.
//
// acmdef.h
//
// AcmCObjArray    : template class holds pointers to data and
//                   destruct them if it's necessary. You should not
//                   care about deleting items
//
// AcmCObjPtrArray : template class holds pointers to data don't
//                   desctruct containing objects. You must care
//                   delete about deleting items
//
// AcmCDesc          : base class for symbol descriptors
// AcmCArrowDesc     : descriptor class for arroheads
// AcmCSymbolDesc    : descriptor class for symbol types
// AcmCGDTSymbolDesc : descriptor class for GDT symbol types
//
/////////////////////////////////////////////////////////////////////

template<class TClass>
class AcmCObjArray : public AcArray<TClass*>
{
public:
  AcmCObjArray<TClass>(int initPhysicalLength = 0, int initGrowLength = 8);
	// we need virtual destructor, since we sometime need to override
	// this class
  virtual ~AcmCObjArray<TClass>();

  int                   append (TClass* value);

	// need to modify behavior - need to delete first.
	AcmCObjArray<TClass>& setAt(int i, TClass* value);
  AcmCObjArray<TClass>& removeAt(int);
  AcmCObjArray<TClass>& removeFirst();
  AcmCObjArray<TClass>& removeLast();
  AcmCObjArray<TClass>& setLogicalLength(int);

private:
	// these must not be used !!!
  AcmCObjArray<TClass>(const AcmCObjArray<TClass>&);
  AcmCObjArray<TClass>& operator = (const AcmCObjArray<TClass>&);
  AcmCObjArray<TClass>& append (const AcmCObjArray<TClass>& array);
};

template<class TClass>
inline AcmCObjArray<TClass>::AcmCObjArray(int initPhysicalLength/* = 0*/, int initGrowLength/* = 8*/)
:	AcArray<TClass*>(initPhysicalLength,initGrowLength)
{
}

template<class TClass>
inline AcmCObjArray<TClass>::~AcmCObjArray()
{
  setLogicalLength(0);
}

template<class TClass>
inline AcmCObjArray<TClass>::AcmCObjArray(const AcmCObjArray<TClass>& src)
{ 
  assert(0);
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::operator = (const AcmCObjArray<TClass>&)
{ 
  assert(0);
  return *this; 
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::append (const AcmCObjArray<TClass>& array)
{	assert(0); return *this;}


template<class TClass>
inline int
AcmCObjArray<TClass>::append(TClass* value)
{ 
  return AcArray<TClass*>::append(value);
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::setAt(int i, TClass* value)
{
  delete at(i);   // delete NULL is ok.
  AcArray<TClass*>::setAt(i, value);
  return *this;
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::removeAt(int i)
{
  TClass *c= at(i);
  if( NULL != c ) delete c;
  AcArray<TClass*>::removeAt(i);
  return *this;
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::removeFirst()
{ return removeAt(0); }

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::removeLast()
{ 
  return removeAt(logicalLength()-1);
}

template<class TClass>
inline AcmCObjArray<TClass>&
AcmCObjArray<TClass>::setLogicalLength(int newLen)
{
  TClass *c;
  if( newLen == length() ) return *this;

	if( newLen < length() ) {
    // delete objects being removed
    for(int i = length()-1; i>=newLen; i--){
      c = at(i);
      if( NULL != c ) delete c;
    }
    AcArray<TClass*>::setLogicalLength(newLen);
  }
	else {
    // init new objects
    int oldLen = length();
    AcArray<TClass*>::setLogicalLength(newLen);
    if (oldLen == 0) {
      setAll(NULL);
    }
    else {
      for(int i = oldLen; i < length(); i ++) 
        AcArray<TClass*>::setAt(i,NULL);
    }
  }
  return *this;
}

// this is just place holder. We don't need it,
// since ACAD provides the template.
template<class TClass>
class AcmCObjPtrArray : public AcArray<TClass*>
{
};

class AcmCDesc
{
public:
  AcmCDesc();
  virtual ~AcmCDesc();

  HBITMAP bitmap() const;
  void    setBitmap(HBITMAP bitmap);

  LPCTSTR description() const;
  void    setDescription(LPCTSTR description);

  int  info() const;
  void setInfo(int value);

private:
  HBITMAP mBitmap;
  CString mDescription;

protected:
  int mInfo;
};

inline
AcmCDesc::AcmCDesc()
: mBitmap(NULL),mInfo(0)
{}

inline
AcmCDesc::~AcmCDesc()
{
  if (!mBitmap) return;
  ::DeleteObject(mBitmap);
}

inline HBITMAP
AcmCDesc::bitmap() const
{ return mBitmap; }

inline void
AcmCDesc::setBitmap(HBITMAP bitmap)
{ mBitmap = bitmap; }

inline LPCTSTR
AcmCDesc::description() const
{ return (LPCTSTR)mDescription; }

inline void
AcmCDesc::setDescription(LPCTSTR description)
{ mDescription = description; }

inline int
AcmCDesc::info() const
{ return mInfo; }

inline void
AcmCDesc::setInfo(int value)
{ mInfo = value; }


class AcmCArrowDesc : public AcmCDesc
{
public:
  AcmCArrowDesc();
  Acm::ArrowType type() const;
  void setType(Acm::ArrowType type);
  bool isSmallIcon() const;
  void setIsSmallIcon(bool bSmall);
private:
  bool m_bSmallIcon;
};

inline AcmCArrowDesc::AcmCArrowDesc()
: AcmCDesc(), m_bSmallIcon(false){}

inline Acm::ArrowType
AcmCArrowDesc::type() const
{ return (Acm::ArrowType)mInfo; }

inline void
AcmCArrowDesc::setType(Acm::ArrowType type)
{ mInfo = (int)type; }

inline bool
AcmCArrowDesc::isSmallIcon() const
{
  return m_bSmallIcon;
}

inline void
AcmCArrowDesc::setIsSmallIcon(bool bSmall)
{
  m_bSmallIcon = bSmall;
}

class AcmCSymbolDesc : public AcmCDesc
{
public:
  AcmCSymbolDesc();

  Adesk::Boolean offered() const;
  void setOffered(Adesk::Boolean check);

  int displayListIndex() const;
  void setDisplayListIndex(int newIndex);

  Acm::SubSymbolType type() const;
  void               setType(Acm::SubSymbolType type);

private:
  Adesk::Boolean mOffered;
  int mDisplayListIndex;
};

inline
AcmCSymbolDesc::AcmCSymbolDesc()
: mOffered(Adesk::kFalse),
  mDisplayListIndex(-1)
{}

inline Adesk::Boolean
AcmCSymbolDesc::offered() const
{ return mOffered; }

inline void
AcmCSymbolDesc::setOffered(Adesk::Boolean check)
{ mOffered = check; }

inline int
AcmCSymbolDesc::displayListIndex() const
{
  return mDisplayListIndex;
}

inline void
AcmCSymbolDesc::setDisplayListIndex(int newIndex)
{
  mDisplayListIndex = newIndex;
}

inline	Acm::SubSymbolType
AcmCSymbolDesc::type() const
{ return (Acm::SubSymbolType)mInfo; }

inline void
AcmCSymbolDesc::setType(Acm::SubSymbolType type)
{ mInfo = (int)type; }

class AcmCGDTSymbolDesc : public AcmCSymbolDesc
{
public:
  Acm::GdtSymbolType type() const;
  void               setType(Acm::GdtSymbolType type);
};

inline	Acm::GdtSymbolType
AcmCGDTSymbolDesc::type() const
{return (Acm::GdtSymbolType)mInfo; }

inline void
AcmCGDTSymbolDesc::setType(Acm::GdtSymbolType type)
{ mInfo = (int)type; }

class AcmCTaperSymbolDesc : public AcmCSymbolDesc
{
public:
  Acm::TaperType type() const;
  void               setType(Acm::TaperType type);
};

inline	Acm::TaperType
AcmCTaperSymbolDesc::type() const
{return (Acm::TaperType)mInfo; }

inline void
AcmCTaperSymbolDesc::setType(Acm::TaperType type)
{ mInfo = (int)type; }

class CVarDlgInfo
{
public:
  CVarDlgInfo();
  virtual ~CVarDlgInfo();

  Adesk::UInt32 helpIndex() const;
  void setHelpIndex(Adesk::UInt32 hlpIdx);

  Adesk::Int16 dlgIndex() const;
  void setDlgIndex(Adesk::Int16 dlgIdx);

  LPCTSTR tooltip() const;
  void setTooltip(LPCTSTR str);

  LPCTSTR label() const;
  void setLabel(LPCTSTR str);

  CStringList& suggested() const;
  void setSuggested(const CStringList& list);
  Adesk::Boolean isSuggested() const;

private:
  Adesk::UInt32 mHelpIndex;
  Adesk::Int16  mDlgIndex;
  CString       mTooltip;
  CString       mLabel;
  CStringList   mSuggested;     // keep list of suggested values
};

inline
CVarDlgInfo::CVarDlgInfo()
: mHelpIndex(0), mDlgIndex(-1), mSuggested()
{}

inline
CVarDlgInfo::~CVarDlgInfo()
{}

inline Adesk::UInt32
CVarDlgInfo::helpIndex() const
{ return mHelpIndex; }

inline void
CVarDlgInfo::setHelpIndex(Adesk::UInt32 hlpIdx)
{ mHelpIndex = hlpIdx; }

inline Adesk::Int16
CVarDlgInfo::dlgIndex() const
{ return mDlgIndex; }

inline void
CVarDlgInfo::setDlgIndex(Adesk::Int16 dlgIdx)
{ mDlgIndex = dlgIdx; }

inline LPCTSTR
CVarDlgInfo::tooltip() const
{ return (LPCTSTR)mTooltip; }

inline void
CVarDlgInfo::setTooltip(LPCTSTR str)
{ mTooltip = str; }

inline LPCTSTR
CVarDlgInfo::label() const
{ return (LPCTSTR)mLabel; }

inline void
CVarDlgInfo::setLabel(LPCTSTR str)
{ mLabel = str; }

inline CStringList&
CVarDlgInfo::suggested() const
{ return (CStringList&) mSuggested; }

inline void
CVarDlgInfo::setSuggested(const CStringList& list)
{
  INT_PTR i, count = list.GetCount();
  for (i=0; i<count; i++)
    mSuggested.AddTail(list.GetAt(list.FindIndex(i)));
}

inline Adesk::Boolean
CVarDlgInfo::isSuggested() const
{
  return (!mSuggested.IsEmpty());
}

class CSymStdTreeItemDesc
{
public:
  virtual ~CSymStdTreeItemDesc();

  virtual CBitmap* GetIcon() const = 0;
  virtual void GetItemText(CString& str) const = 0;
  virtual Acm::ErrorStatus getRevision(CString& rev,
                                       Adesk::UInt16& year) const = 0;

  virtual BOOL OnProperties(CWnd* parentWindow) const = 0;
  virtual BOOL OnFactoryDefaults() = 0;
};

inline
CSymStdTreeItemDesc::~CSymStdTreeItemDesc()
{}

#endif //__ACMDEF_H