/*************************************************************************************************/
/*!
   	@file		main.h
	@author 	Fanzo
 	@date 		2008/5/13
*/
/*************************************************************************************************/
#pragma		once

///////////////////////////////////////////////////////////////////////////////////////////////////
//include files
#include	<windows.h>
#include	<math.h>

using namespace icubic;
using namespace shared;


///////////////////////////////////////////////////////////////////////////////////////////////////
// preprocessor deifne

#define create_item( obj_name , title_obj_name , title , view_height )																								\
	title_obj_name->SetString( title );																																\
	title_obj_name->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( m_es , y ) , isize( p->m_rect.Width() - m_es * 2 , m_ts ) ) );			\
	y += title_obj_name->GetRect().Height();																														\
	obj_name->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( m_es , y ) , isize( p->m_rect.Width() - m_es * 2 , view_height ) ) );		\
	obj_name->SetMsgCallback( ( rControlMsg )( reference )this_object() , 0 );																						\
	y += obj_name->GetRect().Size().height;

///////////////////////////////////////////////////////////////////////////////////////////////////
// type define

///////////////////////////////////////////////////////////////////////////////////////////////////
// classes define

/**************************************************************************************************
"ControlView" class 
**************************************************************************************************/
class ControlView : public View , public IControlMsg
{
	query_begin()
	iface_hook( IControlMsg , IControlMsg_IID )	
	query_end( View )

	msg_view_map_begin()
	msg_view_hook( Create , OnCreate )
	msg_view_hook( Update , OnUpdate )
	msg_view_map_end( View )

// variable member
public:
	instance<SeparateView>			m_color_t;
	instance<ColorCfgView>			m_color;
	instance<SeparateView>			m_anti_dest_t;
	instance<AntiCfgView>			m_anti_dest;
	instance<SeparateView>			m_anti_src_t;
	instance<AntiCfgView>			m_anti_src;
	instance<SeparateView>			m_samplescale_t;
	instance<SampleScaleCfgView>		m_samplescale;
	instance<SeparateView>			m_fillrule_dest_t;
	instance<FillruleCfgView>		m_fillrule_dest;
	instance<SeparateView>			m_fillrule_src_t;
	instance<FillruleCfgView>		m_fillrule_src;
	instance<SeparateView>			m_blender_t;
	instance<BlenderCfgView>			m_blender;

	instance<SeparateView>			m_pathoperator_t;
	instance<PathOperatorCfgView>	m_pathoperator;
	instance<SeparateView>			m_disp_state_t;
	instance<DispOutlineCfgView>		m_disp_state;
	instance<SeparateView>			m_processor_t;
	instance<ProcessorCfgView>		m_processor;

private:
	rControlMsg							m_msg;
	int									m_id;
	
	const int							m_es;
	const int							m_ts;
	
// "IControlMsg" msg	
//=================================================================================================
void cb_call ValueChanged_controlmsg
		(
		int		id
		)
{
	iControlMsg	ck = m_msg.lock();
	if( ck == true )
		ck->ValueChanged_controlmsg( m_id );
}
// msg functions
protected:
//=================================================================================================
void OnCreate
		(
		Create_ViewPM*	p
		)
{
	int		y = m_es;
	create_item( m_color , m_color_t , L"color" , 65 );
	create_item( m_samplescale , m_samplescale_t , L"samplescale" , 20 );
	create_item( m_anti_dest , m_anti_dest_t , L"dest antialias" , 35 );
	create_item( m_anti_src , m_anti_src_t , L"src antialias" , 35 );
	create_item( m_fillrule_dest , m_fillrule_dest_t , L"dest fillrule" , 30 );
	create_item( m_fillrule_src , m_fillrule_src_t , L"src fillrule" , 30 );
	create_item( m_blender , m_blender_t , L"blender" , 20 );

	create_item( m_pathoperator , m_pathoperator_t , L"operator" , 35 );
	create_item( m_disp_state , m_disp_state_t , L"disp switch" , 45 );
	create_item( m_processor , m_processor_t , L"processor" , 20 );

	m_color->SetValue( rgba( 127 , 191 , 121 , 255 ) );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	DrawConfigBack( (iSurfaceDest)p->m_surface , GetRect().Size() );
}

// public functions
public:
//=================================================================================================
ControlView() : m_id( 0 ) , m_es( 5 ) , m_ts( 11 )
{
}
//=================================================================================================
void SetMsgCallback
		(
		rControlMsg&		msg , 
		int					id
		)
{
	m_msg	= msg;
	m_id	= id;
}
};
/**************************************************************************************************
"MainView" class 
**************************************************************************************************/
class MainView : public View , public IControlMsg
{
	query_begin()
	iface_hook( IControlMsg , IControlMsg_IID )
	query_end( View )

	msg_view_map_begin()
	msg_view_hook( Create , OnCreate )
	msg_view_hook( Update , OnUpdate )
	msg_view_hook( Size , OnSize )
	msg_view_hook( LDragStart , OnLDragStart )
	msg_view_hook( LDrag , OnLDrag )
	msg_view_hook( LDragEnd , OnLDragEnd )
	msg_view_hook( LDragCancel , OnLDragCancel )
	msg_view_map_end( View )

// variable member
private:
	instance<ControlView>			m_control;
	instance<TimeCfgView>			m_time;

	instance<PathSegmentToOutline>	m_path;
	instance<Outline>				m_outline_dest , m_outline_src;
	instance<PaintSolidColor>		m_source;
	instance<OutlineGenPaint>		m_gen;
	instance<EdgemapOutline>			m_map_dest , m_map_src;
	instance< RendererOutline >		m_renderer;

	int									m_edit_pnt;
	fvector2							m_pnt[14];

	const int							m_handle_r;
	const rgb							m_bc;
	const rgb							m_hlc_src;
	const rgb							m_hcc_src;
	const rgb							m_hlc_dest;
	const rgb							m_hcc_dest;
	const rgb							m_oc;
	const rgb							m_opc;
	const rgba							m_pc;
	
// msg functions
private:
//=================================================================================================
void cb_call ValueChanged_controlmsg
		(
		int		id
		)
{
	RequireUpdate( irect( ivector2( 0 , 0 ) , GetRect().Size() ) , false );
}
// functions
private:
//=================================================================================================
void DrawHandle
		(
		iSurfaceDest&	surface
		)
{
	isize		size= GetRect().Size();			
	faffine		aff = faffine::GetMove( fvector2( ( float )size.width / 2.0f , ( float )size.height / 2.0f ) );

	fvector2	pnt[_countof( m_pnt )];
	int			pntnum	= 0;
	int			i;

	pntnum	= _countof( m_pnt );
	for( i = 0 ; i < _countof( m_pnt ) ; i++ )
		pnt[i] = aff.Transform( m_pnt[i] );
	DrawLine( surface , pnt[1] , pnt[2] , 1.0f , m_hlc_dest );
	DrawLine( surface , pnt[2] , pnt[3] , 1.0f , m_hlc_dest );
	DrawLine( surface , pnt[3] , pnt[4] , 1.0f , m_hlc_dest );
	DrawLine( surface , pnt[4] , pnt[5] , 1.0f , m_hlc_dest );
	DrawLine( surface , pnt[5] , pnt[6] , 1.0f , m_hlc_dest );

	DrawLine( surface , pnt[8] , pnt[9] , 1.0f , m_hlc_src );
	DrawLine( surface , pnt[9] , pnt[10] , 1.0f , m_hlc_src );
	DrawLine( surface , pnt[10] , pnt[11] , 1.0f , m_hlc_src );
	DrawLine( surface , pnt[11] , pnt[12] , 1.0f , m_hlc_src );
	DrawLine( surface , pnt[12] , pnt[13] , 1.0f , m_hlc_src );

	for( i = 0 ; i < pntnum / 2 ; i++ )
		DrawCircle( surface , pnt[i] , ( float )m_handle_r , m_hcc_dest );
	for( i = pntnum / 2 ; i < pntnum ; i++ )
		DrawCircle( surface , pnt[i] , ( float )m_handle_r , m_hcc_src );
}
// msg functions
private:
//=================================================================================================
void OnCreate
		(
		Create_ViewPM*	p
		)
{
	m_control->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( 1 , 1 ) , isize( 130 , 450 ) ) );
	m_control->SetMsgCallback( ( rControlMsg )( reference )this_object() , 100 );

	m_time->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( 135 , 0 ) , isize( 300 , 16 ) ) );
	m_time->SetMsgCallback( ( rControlMsg )( reference )this_object() , 0 );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	ColorBlt( (iSurfaceDest)p->m_surface , p->m_rect , m_bc , Onezero_BltBlendType );	
	m_time->BeginMeasure();
	isize		size= GetRect().Size();			
	faffine		aff = faffine::GetMove( fvector2( ( float )size.width / 2.0f , ( float )size.height / 2.0f ) );

	{
		m_outline_dest->Reset();
		m_gen->SetSampleScale( m_control->m_samplescale->GetValue() );
		m_path->Begin( (iOutline)m_outline_dest , (iOutlineGen)m_gen );
		m_path->Move( m_pnt[0] , aff , true );
		m_path->Line( 1 , &m_pnt[1] );
		m_path->BezierQ( 2 , &m_pnt[2] );
		m_path->BezierC( 3 , &m_pnt[4] );
		m_path->End();

		m_map_dest->Initialize( m_control->m_anti_dest->GetValue() , p->m_rect );
		m_map_dest->BeginOutline();
		m_map_dest->SetOutline( (iOutline)m_outline_dest , faffine() );
		m_map_dest->EndOutline( m_control->m_fillrule_dest->GetValue() );
	}
	{
		m_outline_src->Reset();
		m_gen->SetSampleScale( m_control->m_samplescale->GetValue() );
		m_path->Begin( (iOutline)m_outline_src , (iOutlineGen)m_gen );
		m_path->Move( m_pnt[7] , aff , true );
		m_path->Line( 1 , &m_pnt[8] );
		m_path->BezierQ( 2 , &m_pnt[9] );
		m_path->BezierC( 3 , &m_pnt[11] );
		m_path->End();

		m_map_src->Initialize( m_control->m_anti_src->GetValue() , p->m_rect );
		m_map_src->BeginOutline();
		m_map_src->SetOutline( (iOutline)m_outline_src , faffine() );
		m_map_src->EndOutline( m_control->m_fillrule_src->GetValue() );
	}
	m_map_dest->Operate( m_control->m_pathoperator->GetValue() , (iEdgemapOutlineInfo)m_map_src );
	m_source->SetColor( m_control->m_color->GetValue() );
	m_renderer->SetBlender( m_control->m_blender->GetValue() );
	m_renderer->SetPaint( ( iPaint )m_source );
	m_renderer->Render( (iSurfaceDest)p->m_surface , (iEdgemapOutlineInfo)m_map_dest , &p->m_rect , 1 );
	m_time->EndMeasure();

	if( m_control->m_disp_state->GetOutlineState() == true )
	{
		DrawOutline( (iSurfaceDest)p->m_surface , ( iOutline )m_outline_dest , 1.0f , m_oc );
		DrawOutline( (iSurfaceDest)p->m_surface , ( iOutline )m_outline_src , 1.0f , m_oc );
	}
	if( m_control->m_disp_state->GetSampleState() == true )
	{
		DrawOutlinePoint( (iSurfaceDest)p->m_surface , ( iOutline )m_outline_dest , m_opc );
		DrawOutlinePoint( (iSurfaceDest)p->m_surface , ( iOutline )m_outline_src , m_opc );
	}
	if( m_control->m_disp_state->GetHandleState() == true )
		DrawHandle( (iSurfaceDest)p->m_surface );
}
//=================================================================================================
void OnSize
		(
		Size_ViewPM*	p
		)
{
}
//=================================================================================================
void OnLDragStart
		(
		LDragStart_ViewPM*	p
		)
{
	if( m_control->m_disp_state->GetHandleState() == false )
		return;

	isize		size= GetRect().Size();			
	faffine		aff = faffine::GetMove( fvector2( ( float )size.width / 2.0f , ( float )size.height / 2.0f ) );

	int	i;
	for( i = 0 ; i < _countof( m_pnt ) ; i++ )
	{
		fvector2	pnt = aff.Transform( m_pnt[i] );
		irect		rc( ( int )pnt.x - m_handle_r , ( int )pnt.y - m_handle_r , ( int )pnt.x + m_handle_r , ( int )pnt.y + m_handle_r );
		if( true == rc.IsInside( p->m_pos ) )
		{
			m_edit_pnt = i;
			break;
		}
	}
}
//=================================================================================================
void OnLDrag
		(
		LDrag_ViewPM*	p
		)
{
	if( m_edit_pnt == -1 )
		return;

	isize		size= GetRect().Size();			
	faffine		aff = faffine::GetMove( fvector2( ( float )size.width / 2.0f , ( float )size.height / 2.0f ) );
	faffine		raff	= aff.Inverse();
	
	m_pnt[ m_edit_pnt ]	= raff.Transform( fvector2( ( float )p->m_pos.x , ( float )p->m_pos.y ) );
	RequireUpdate( irect( ivector2( 0 , 0 ) , GetRect().Size() ) , false );
}
//=================================================================================================
void OnLDragEnd
		(
		LDragEnd_ViewPM*	p
		)
{
	m_edit_pnt = -1;
}
//=================================================================================================
void OnLDragCancel
		(
		LDragCancel_ViewPM*	p
		)
{
	m_edit_pnt = -1;
}
// public functions
public:
//=================================================================================================
MainView() : 
		m_handle_r( 5 ) , 
		m_edit_pnt( -1 ) , 
		m_bc( 255 , 255 , 235 ) ,
		m_hlc_dest( 40,121,121) , 
		m_hcc_dest( 40,121,121) , 
		m_hlc_src( 121,121,40) , 
		m_hcc_src( 121,121,40) , 
		m_oc( 60 , 100 , 60 ) , 
		m_opc( 30,100,100 ) , 
		m_pc( 127 , 191 , 121 , 255 )
{
	m_pnt[0]	= fvector2( -100.0f , -50.0f );
	m_pnt[1]	= fvector2( 0.0f , -100.0f );
	m_pnt[2]	= fvector2( 100.0f , -100.0f );
	m_pnt[3]	= fvector2( 100.0f , 0.0f );
	m_pnt[4]	= fvector2( 100.0f , 50.0f );
	m_pnt[5]	= fvector2( 50.0f , 0.0f );
	m_pnt[6]	= fvector2( 0.0f , 100.0f );

	m_pnt[7]	= fvector2( -100.0f , 0.0f );
	m_pnt[8]	= fvector2( -100.0f , -100.0f );
	m_pnt[9]	= fvector2( 100.0f , -100.0f );
	m_pnt[10]	= fvector2( 100.0f , 0.0f );
	m_pnt[11]	= fvector2( 100.0f , 100.0f );
	m_pnt[12]	= fvector2( 0.0f , 100.0f );
	m_pnt[13]	= fvector2( -100.0f , 100.0f );
}
};

///////////////////////////////////////////////////////////////////////////////////////////////////
// global variable define

///////////////////////////////////////////////////////////////////////////////////////////////////
// global functions define





