/*********************************************************************
*	created:	2007/4/12
*	pathname:	Source\prj\Lib\CMDS\IcadEdJig.h
*	author:		李明锦 北京浩辰
*	
*	purpose:	class IcadEdJig header file
*********************************************************************/

#ifndef ICAD_EDIT_JIG__H
#define ICAD_EDIT_JIG__H

///////////////////////////////////////////////////////////////////////
// 数据类型定义，以后可能去掉
typedef char IcChar;
typedef const IcChar* PCIcChar;

//typedef double sds_point[3];
//typedef long sds_name[2];
//struct sds_resbuf;

typedef sds_point IcPoint3d;

///////////////////////////////////////////////////////////////////////
//
#pragma pack (push, 8)

class  IcSelset;
class  IcEdImpJig;
class  IcEntityContainer;

/** class IcObjectId
  Wrap up sds_name of Selection Set which contains new "Append" Entities.
  And the SelSet sds_name will AUTO FREE.

  // 封装选择集: 新创建的一个或多个实体添加到 IcObjectId 所包含的选择集
  // 目的: 与ACAD兼容，同时方便客户程序访问新建实体
  // 注意: 会自动释放选择集, 因为所有权是 IcObjectId 的
 */
class IcObjectId
{
	friend class IcEdJig;
	friend class IcEdImpJig;
public:
	IcObjectId();
	IcObjectId(const IcObjectId&);
	~IcObjectId();

	IcObjectId& operator= (const IcObjectId&);

	int getEntname(int idx, sds_name ent) const;
	size_t getSize() const;

private:
	IcSelset *m_pSS;
	void attach(IcSelset*);
	void detach();
};

/** class IcEntityPtr
  Wrap up sds_resbuf list, which will be drawn while draging and will append to DataBase if succeed.
  WARNING: Application MUST FREE sds_resbuf.

  // 封装 sds_resbuf: 拖动过程中显示实体链表，同时通过调用 append(), 该实体链表可以永久添加到数据文件里.
  // 目的: 与ACAD兼容，同时实现任意对象的拖动效果
  // 说明: 客户程序更新绘制时，最好调用 clear() 清除旧实体链表，不然会累积.
  // 注意: 客户程序必须释放sds_resbuf内存, 因为它们的所有权属于客户程序.
 */
class IcEntityPtr
{
	friend class IcEdJig;
	friend class IcEdImpJig;
public:
	IcEntityPtr();
	IcEntityPtr(const IcEntityPtr&);
	~IcEntityPtr();

	IcEntityPtr& operator= (const IcEntityPtr&);

	bool add(const sds_resbuf* pResbuf);

	void clear();

	size_t size() const;

private:
	IcEntityContainer *m_pEntityContainer;
	void attach(IcEntityContainer*);
	void detach();
};


/**
    class IcEdJig, ICAD Edit Jig Base class.
	// 这个类就不说明了.
 */
class IcEdJig 
{
public:
    //ACRX_DECLARE_MEMBERS(AcEdJig);

	/************************************************************************/
	/*                         Enumerations                                 */
	/************************************************************************/
	/**
		enum UserInputControls
	 */
	typedef enum UserInputControls {
		kGovernedByOrthoMode         = 0x0001,
		kNullResponseAccepted        = 0x0002,
		kDontEchoCancelForCtrlC      = 0x0004,
		kDontUpdateLastPoint         = 0x0008,
		kNoDwgLimitsChecking         = 0x0010,
		kNoZeroResponseAccepted      = 0x0020,
		kNoNegativeResponseAccepted  = 0x0040,
		kAccept3dCoordinates         = 0x0080,
		kAcceptMouseUpAsPoint        = 0x0100,
		kAnyBlankTerminatesInput     = 0x0200,
		kInitialBlankTerminatesInput = 0x0400,
		kAcceptOtherInputString      = 0x0800,
		kGovernedByUCSDetect         = 0x1000,
		kNoZDirectionOrtho           = 0x2000
    };

	/**
		enum DragStatus
	 */
	typedef enum DragStatus {
        kModeless       = -17,
        kNoChange       = -6,
        kCancel         = -4,
        kOther          = -3,
        kNull           = -1,
        kNormal         = 0,
        kKW1,
        kKW2,
        kKW3,
        kKW4,
        kKW5,
        kKW6,
        kKW7,
        kKW8,
        kKW9
    };

	/**
		enum CursorType
	 */
	typedef enum CursorType {
        kNoSpecialCursor = -1,           // No Special Cursor Specified
        kCrosshair = 0,                  // Full Screen Cross Hair. 
        kRectCursor,                     // Rectangular cursor. 
        kRubberBand,                     // Rubber band line. 
        kNotRotated,                     // NotRotated Type. 
        kTargetBox,                      // Target Box Type. 
        kRotatedCrosshair,               // Rotated Crosshair w/ rubber band. 
        kCrosshairNoRotate,              // Crosshairs forced non-rotated. 
        kInvisible,                      // Invisible cursor. 
        kEntitySelect,                   // Entity selection target cursor. 
        kParallelogram,                  // Parallelogram cursor. 
        kEntitySelectNoPersp,            // Pickbox, suppressed in persp. 
        kPkfirstOrGrips,                 // Auto-select cursor. 
        kCrosshairDashed                 // 15 dashed style crosshair cursor
    };

	/************************************************************************/
	/*                  Constructors & Destructors                          */
	/************************************************************************/
	/**
		CTor & DTor
	 */
	IcEdJig();
	virtual ~IcEdJig();

	/************************************************************************/
	/*                          Processing                                  */
	/************************************************************************/

	/** 
	  drag(): 处理函数(Processing), 用户可以调用, 但不能重载
	  说明：Jig 内部拖拽处理
	  返回：DragStatus - 最终拖拽状态
	 */
    DragStatus drag();

	/** 
	  append(): 处理函数(Processing), 用户可以调用, 但不能重载
	  说明：拖拽处理成功后, 用户可以把实体添加到数据库里
	  返回：IcObjectId - 成功则 m_ename[1] != NULL; 失败则 m_ename[1] == NULL
	  注释：
        In the jig operation, Calls the entity() function to get IcEntityPtr of the entities, 
        appends these entities to default space (that is, *Model or *Paper) of the current database, draws them, 
        and returns their IcObjectId(Selection Set). Once appended to the database, the object's memory is
        the responsibility of the database and must not be deleted by the application.
        But IcObjectId which is SelSet, MUST FREE in the application. By default, DTor of IcObjectId will free it.
	 */
    IcObjectId append();
	
	/************************************************************************/
	/*                         Setup & Query                                */
	/************************************************************************/

	/** 
	  setKeywordList(): 参数设置函数(Setup), 用户可调用, 无需重载
	  说明：设置输入关键词列表
	  参数：PCIcChar pKeyWord - 输入关键词列表字符串指针
	  注释：
        Uses a copy of keywordList as the keyword list for subsequent acquireXxxx() functions calls. 
        The keyword list can contain up to 30 keywords. The list form is a follows:
          The keyword list is a space delimited list of the form "Key1 KEy2 KEY3,ABBREV3". 
          Abbreviations are optional, and two methods of specifying them are supported. 
          1. The required portion can be upper case and the rest lower case, 
             or the required portion can be repeated, separated from the keyword by a comma. 
          2. The second method is intended to facilitate translation to foreign languages that may have difficulty 
		     with case conversion. 
          In either method, the length of the required portion is simply used as the minimum length 
		  that must match exactly. (For the comma-delimited method, it is assumed that the abbreviation string 
		  is a proper subset of the keyword start.)
	 */
    void setKeywordList(PCIcChar pKeyWord);

    /**
	  keywordList(): 参数查询函数(Query), 用户可调用, 无需重载
	  说明：获取 setKeywordList() 所设置的输入关键词列表, 若无，则为空字符串
	  返回：PCIcChar - 输入关键词列表字符串指针
	  注释：参考上面
        This is not a pointer to a string copy, so do not make any attempts to delete the string pointed.
     */
    PCIcChar keywordList();

    /**
	  setDispPrompt(): 参数设置函数(Setup), 用户可调用, 无需重载
	  说明：设置提示内容
	  参数：PCIcChar pPrompt - 新的提示字符串, 支持 printf() 格式
	        ... - printf()格式可选的参数(optional printf() style formatting codes)
	  注释：
        Uses a copy of dispPrompt as the new prompt string for subsequent drag operations. 
	    The dispPrompt string may contain standard printf() style formatting codes with 
		additional arguments following dispPrompt, one for each formatting code, 
		in the same way that printf() and sds_printf() work.
	    This function should be called just before calling the drag() method that uses the prompt being set.
	 */
    void setDispPrompt(PCIcChar pPrompt, ...);

    /**
	  dispPrompt(): 参数查询函数(Query), 用户可调用, 无需重载
	  说明：获取 setDispPrompt() 所设置的、格式化后的提示字符串, 若无，则为空字符串
	  返回：PCIcChar - 提示内容字符串指针
	  注释：参考上面
        This is not a pointer to a string copy, so do not make any attempts to delete the string pointed.
	 */
    PCIcChar dispPrompt();

    /**
	  setSpecialCursorType(): 参数设置函数(Setup), 用户可调用, 无需重载
	  说明：设置特定的光标类型
	  参数：CursorType ctype - 新的光标类型
	 */
    void setSpecialCursorType(CursorType ctype);

    /**
	  specialCursorType(): 参数查询函数(Query), 用户可调用, 无需重载
	  说明：获取 setSpecialCursorType() 所设置的光标类型, 若无，则为 kNoSpecialCursor
	  返回：参数：CursorType - 光标类型
	 */
    CursorType specialCursorType();

    /**
	  setUserInputControls(): 参数设置函数(Setup), 用户可调用, 无需重载
	  说明：设置用户输入控制方式
	  参数：UserInputControls uic - 输入控制方式标记
	  注释：
	    Sets the user input control attributes for the next call to acquireXxxx() to uic.
	    The value of uic can be a single, or multiple UserInputControls together. 
	 */
	void setUserInputControls(UserInputControls uic);

    /**
	  userInputControls(): 参数查询函数(Query), 用户可调用, 无需重载
	  说明：获取用户输入控制方式值
	  返回：UserInputControls - 输入控制方式标记
	  注释：参考上面
	 */
    UserInputControls userInputControls();

	/************************************************************************/
	/*                          User Input                                  */
	/************************************************************************/

    /**
	  acquireXXX(): 用户数据输入函数(User Input), 用户可调用, 无需重载  
	  返回：当前拖拽状态
	 */
    /** acquireString() 
	  参数：IcChar *str - 字符串缓存指针
	        size_t size - 字符串缓存大小
	  注意：这个函数与ACAD不兼容，但更合理
	 */
    DragStatus acquireString(IcChar *str, size_t size);

    /** acquireAngle() 
	  参数：double &ang - 角度，(0,0,0) 为基点
	 */
    DragStatus acquireAngle(double &ang);
    /** acquireAngle() 
	  参数：double &ang - 角度，相对于基点 basePnt
	        const IcPoint3d& basePnt - 基点
	 */
    DragStatus acquireAngle(double &ang, const IcPoint3d& basePnt);

    /** acquireDist() 
	  参数：double &dist - 距离，(0,0,0) 为基点
	 */
    DragStatus acquireDist(double &dist);
    /** acquireDist() 
	  参数：double &dist - 距离，相对于基点 basePnt
	        const IcPoint3d& basePnt - 基点
	 */
    DragStatus acquireDist(double &dist, const IcPoint3d& basePnt);

    /** acquirePoint() 
	  参数：IcPoint3d& pnt - 位置点，(0,0,0) 为基点
	 */
    DragStatus acquirePoint(IcPoint3d& pnt);
    /** acquirePoint() 
	  参数：IcPoint3d& pnt - 位置点，相对于基点 basePnt
	        const IcPoint3d& basePnt - 基点
	 */
    DragStatus acquirePoint(IcPoint3d& pnt, const IcPoint3d& basePnt);

	/************************************************************************/
	/*                       *Overridden*                                   */
	/************************************************************************/

	/**
	  entity(): 重载函数(Overridden), 用户调用, 必须重载
	  说明：获取参与拖拽的 IcEntityPtr 对象
	  返回：IcEntityPtr - 参与拖拽的 IcEntityPtr 对象, 对象不是空集时，才可以参与拖拽.
	  注释：
        This function is required to be overridden to return a IcEntityPtr object.
        The same object throughout the course of an drag() call. 
        It is the entities that drag() drags, and that update() updates.
        Application's command normally creates new instance of the acquiring entities 
        which wish to drag, are stored in IcEntityPtr, and partially initialize it 
		prior to using drag(), update(), or append().
	 */
    virtual IcEntityPtr entity() const;

    /**
	  sampler(): 重载函数(Overridden), 用户调用, 必须重载
	  说明：取样处理函数，ICAD 系统主动调用，客户程序需要通过它来通知 ICAD 系统是否需要更新
	  返回：DragStatus - 当前拖拽状态, 若为 kNoChange, 则 ICAD 系统不更新 IcEntityPtr 对象.
	  注释：
        This overridden function is called within drag() to solicit entity-defining input from the user. 
        Before sampler() is called, ICAD's input system is primed to accept "tentative" input.
		If sampler() gets usable input, it must make it available for update() to define the state of IcEntityPtr. 
        It should NOT modify the entities, as it may be called at any time during entity elaboration, 
        and such modification could confuse the elaboration code.
	 */
	virtual DragStatus sampler(); 

	/**
	  update(): 重载函数(Overridden), 用户调用, 必须重载
	  说明：对象更新处理函数，ICAD 系统通过它来通知客户程序更新 IcEntityPtr 对象
	  返回：bool - 是否更新成功, ICAD 系统检测返回状态，成功则重绘拖拽对象.
	  注释：
	  This overridden function is called subsequent to a successful call to sampler() and 
	  before the dragger starts an elaboration of the IcEntityPtr. It may also be called by 
	  the client at will. It has the job of applying sampler()'s input to the acquiring entities.
	  It can fail, meaning that the sampler input doesn't define a valid IcEntityPtr. 
	  It signifies this by returning 'false', or should return 'true' if successfully completes.
	 */
	virtual bool update();

	/**
	  标注相关，不支持
	  */
	//virtual IcDbDimDataPtrArray* dimData(const double dimScale);
	//virtual ErrorStatus setDimValue(const AcDbDimData* dimData, const double dimValue); 

private:
	/**
	  内部使用变量，Jig 具体实现类指针
	  */
	IcEdImpJig*  m_pImpJig;
};


#pragma pack (pop)
//
///////////////////////////////////////////////////////////////////////


#endif //ICAD_EDIT_JIG__H

