/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/* ***************************************************** */
/********************************************************************/
/**
 * @file CommandStateOwner.h
 * @brief クラス MGCommandStateOwner の宣言
 */
#if !defined(AFX_MGCommandStateOwner_H__A4AF74B6_A496_496F_8012_CDFF87747D18__INCLUDED_)
#define AFX_MGCommandStateOwner_H__A4AF74B6_A496_496F_8012_CDFF87747D18__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "Common/CommandBase.h"

/// class MGCommandStateOwner
///
/// コマンドは一般的に複数のステップを持つ
/// 「投影コマンド」を例に考えると:
/// 1. 投影する曲線を決めるステップ
/// 2. どこに投影するのかを決めるステップ
/// 3. 投影の計算をするステップ
/// となる
///
/// その各ステップを MGCommandBase の派生クラスで表現し
/// メインのコマンドをMGCommandStateOwnerで表現する
///
/// MGCommandStateOwnerが現在のステップを保持しており
/// 次のステップは現在のステップに相当するオブジェクトが保持する
///
/// このステップの変更はMGCommandStateOwner::OnKeyDown等の
/// キー入力・マウス入力関数終了時に行われることがある
///
/// またドキュメントの標準コマンドオブジェクトとして
/// このクラスそのものが(==派生なしで)用いられている
class MGCommandStateOwner : public MGCommandBase{
public:
	
//	MGCommandStateOwner();

	/// static領域にあるオブジェクトのためのコンストラクタ
	/// ドキュメントの「標準状態」のコマンドオブジェクトである
	MGCommandStateOwner(fugenDoc* pDoc);

	/// 派生クラス用コンストラクタ
	/// ドキュメントとコマンドIDを指定してオブジェクトを生成する
	MGCommandStateOwner(fugenDoc* pDoc, UINT nID);

	virtual ~MGCommandStateOwner();

	///MGCommandStateOwner::initiate_tool() always return false.
	virtual bool initiate_tool();  // override
	virtual bool terminate_tool(bool cancel); // override

	///Set the current state command.
	void set_child_current_command(
		MGCommandBase* currentState
	);

	///Set the next state command.
	void set_child_next_command(
		MGCommandBase* nextState
	);

	///Clear the current command state.
	///This will cause the termination of this command.
	void clear_state();

	///Get the next command.
	MGCommandBase* GetNextState(){ return m_next;}

	/// 現在のステップを表現するコマンドオブジェクトを返す
	MGCommandBase* GetCurState(){ return m_state;}
	const MGCommandBase* GetCurState() const{ return m_state;}

	///update snap mode for locate.
	virtual void updateSnapMode(const MGSnapAttrib& sattrib);

public:
	// MGCommandStateOwnerのキー入力・マウス入力関数では
	// ステップオブジェクトのメンバ呼び出しとステップの進行を行う

	virtual bool OnKeyDown(fugenView* window, UINT nChar,UINT nRepCnt, UINT nFlags);
	virtual bool OnKeyUp(fugenView* window, UINT nChar, UINT nRepCnt, UINT nFlags);
	virtual bool OnLButtonDblClk(fugenView* window,UINT nFlags, CPoint point);
	virtual bool OnLButtonDown(fugenView* window,UINT nFlags, CPoint point);
	virtual bool OnLButtonUp(fugenView* window,CPoint old_point,UINT nFlags, CPoint point);
	virtual bool OnMouseMove(fugenView* window,UINT nFlags, CPoint point);
	virtual bool OnMouseWheel(fugenView* window,UINT nFlags, short zDelta, CPoint pt);
	virtual bool OnRButtonDblClk(fugenView* window,UINT nFlags, CPoint point);
	virtual bool OnRButtonDown(fugenView* window,UINT nFlags, CPoint point);
	virtual bool OnRButtonUp(fugenView* window,CPoint old_point,UINT nFlags, CPoint point);
	virtual bool OnSetCursor(fugenView* pView, CWnd* pWnd, UINT nHitTest, UINT message);

	virtual void ModifyContextMenu(CMenu& popup);

	virtual bool CanHandle(UINT nID) const;
	virtual bool HandleMessage(UINT nID);
	virtual bool HandleUpdateUI(UINT nID, CCmdUI* pCmdUI);
	
protected:
	// このコマンドの現在のステップを表すコマンドオブジェクトを指す
	// 次のステップがない場合に0をとる
	MGCommandBase* m_state;

	// コマンドの各状態をMGCommandBaseの派生クラスで表現するが
	// どの状態も次の状態を決めることができる
	// そのオブジェクトをm_nextとする
	//
	// m_nextはMGCommandBaseの派生クラスが
	// こうした状態クラスであるときに有効なメンバである
	MGCommandBase*    m_next;

	// 次のステップに移行するときに呼ばれる関数
	void ChangeState();

	friend class MGCommandBase;
};

#endif // !defined(AFX_DEFAULTCMD_H__A4AF74B6_A496_496F_8012_CDFF87747D18__INCLUDED_)
