/*************************************************************************************************/
/*!
   	@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;

#define create_item_w( obj_name , title_obj_name , title , view_width )																								\
	title_obj_name->SetString( title );																																\
	title_obj_name->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( x , m_es ) , isize( view_width , m_ts ) ) );							\
	obj_name->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( x , title_obj_name->GetRect().Height() + m_es ) , isize( view_width , p->m_rect.Height() - title_obj_name->GetRect().Height() - m_es * 2 ) ) );		\
	obj_name->SetMsgCallback( ( rControlMsg )( reference )this_object() , 0 );																						\
	x += view_width;

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

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

/**************************************************************************************************
"DispCfgView" class 
**************************************************************************************************/
class DispCfgView : public CheckCfgView
{
// public functions
public:
//=================================================================================================
DispCfgView()
{
	SetCheckNum( 4 );
	SetString( 0 , L"disp clip" );
	SetString( 1 , L"disp paint" );
	SetString( 2 , L"disp stroke" );
	SetString( 3 , L"disp handle" );
}
//=================================================================================================
bool GetClipState()
{
	return GetValue( 0 );
}
//=================================================================================================
bool GetPathState()
{
	return GetValue( 1 );
}
//=================================================================================================
bool GetStrokeState()
{
	return GetValue( 2 );
}
//=================================================================================================
bool GetHandleState()
{
	return GetValue( 3 );
}
};
/**************************************************************************************************
"AlphaCfgView" class 
**************************************************************************************************/
class AlphaCfgView : public View , public ISliderMsg
{
	query_begin()
	iface_hook( ISliderMsg , ISliderMsg_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
private:
	instance<Slider>	m_alpha;
	instance<Font>		m_font;
	
	rControlMsg			m_msg;
	int					m_id;
	
	const int			m_sh;
	const int			m_info_w;
	
// ctrlmsg functions
private:
//=================================================================================================
void cb_call ValueChanged_slider
		(
		int		id
		)
{
	RequireUpdate( irect( ivector2( 0 , 0 ) , GetRect().Size() ) , false );
	iControlMsg	ck = m_msg.lock();
	if( ck == true )
		ck->ValueChanged_controlmsg( m_id );
}
// msg functions
protected:
//=================================================================================================
void OnCreate
		(
		Create_ViewPM*	p
		)
{
	m_alpha->Create
			( 
			( rViewParentCtrl )( reference )this_object() , 
			irect( ivector2( 0 , 0 ) , isize( p->m_rect.Size().width - m_info_w , m_sh ) )
			);
	m_alpha->SetValue( 1.0f );
	m_alpha->SetMsgCallback( ( rSliderMsg )( reference )this_object() , 100 );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	wchar_t	text[ 256 ];
	cb_swprintf( text , L"A:%d" , GetValue() );
	DrawText( (iSurfaceDest)p->m_surface , fvector2( ( float )( GetRect().Size().width - m_info_w ) , ( float )(  m_sh / 2 ) ) , text , ( iFont )m_font , rgb(0,0,0) , Center_TextAlign );
}

// public functions
public:
//=================================================================================================
AlphaCfgView() : m_sh( 15 ) , m_info_w( 30 ) , m_id( 0 )
{
	cb_verify( true == m_font->Create( fsize( 0.0f , 10.0f ) , L"Tahoma" , Roman_FontCharsetType , 400 , false ) );
}
//=================================================================================================
void SetMsgCallback
		(
		rControlMsg&		msg , 
		int					id
		)
{
	m_msg	= msg;
	m_id	= id;
}
//=================================================================================================
uint8 GetValue()
{
	return ( uint8 )( m_alpha->GetValue() * 255.0f );
}
};
/**************************************************************************************************
"Control1View" class 
**************************************************************************************************/
class Control1View : 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_anti_t;
	instance<AntiCfgView>			m_anti;

	instance<SeparateView>			m_alpha_t;
	instance<AlphaCfgView>			m_alpha;
	instance<SeparateView>			m_pathoperator_t;
	instance<PathOperatorCfgView>	m_pathoperator;
	instance<SeparateView>			m_fillrule_t;
	instance<FillruleCfgView>		m_fillrule;

	instance<SeparateView>			m_blender_t;
	instance<BlenderCfgView_gp>		m_blender;

	instance<SeparateView>			m_disp_state_t;
	instance<DispCfgView>			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_anti , m_anti_t , L"antialias" , 35 );
	create_item( m_pathoperator , m_pathoperator_t , L"path operator" , 35 );
	create_item( m_alpha , m_alpha_t , L"alpha" , 20 );
	create_item( m_fillrule , m_fillrule_t , L"path fillrule" , 30 );
	create_item( m_blender , m_blender_t , L"blender" , 20 );
	create_item( m_disp_state , m_disp_state_t , L"disp switch" , 60 );
	create_item( m_processor , m_processor_t , L"processor" , 20 );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	DrawConfigBack( (iSurfaceDest)p->m_surface , GetRect().Size() );
}
// public functions
public:
//=================================================================================================
Control1View() : m_id( 0 ) , m_es( 5 ) , m_ts( 11 )
{
}
//=================================================================================================
void SetMsgCallback
		(
		rControlMsg&		msg , 
		int					id
		)
{
	m_msg	= msg;
	m_id	= id;
}
};
/**************************************************************************************************
"Control2View" class 
**************************************************************************************************/
class Control2View : 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<PenCfgView>			m_pen;

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;
	m_pen->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( m_es , y ) , isize( p->m_rect.Width() - m_es * 2 , 490 ) ) );
	m_pen->SetMsgCallback( ( rControlMsg )( reference )this_object() , 0 );
	y += m_pen->GetRect().Size().height;
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	DrawConfigBack( (iSurfaceDest)p->m_surface , GetRect().Size() );
}

// public functions
public:
//=================================================================================================
Control2View() : m_id( 0 ) , m_es( 5 ) , m_ts( 11 )
{
}
//=================================================================================================
void SetMsgCallback
		(
		rControlMsg&		msg , 
		int					id
		)
{
	m_msg	= msg;
	m_id	= id;
}
};

/**************************************************************************************************
"BrushView" class 
**************************************************************************************************/
class BrushView : 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_brush_paint_t;
	instance<BrushCfgView>			m_brush_paint;
	instance<SeparateView>			m_brush_stroke_t;
	instance<BrushCfgView>			m_brush_stroke;

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		x = m_es;
	create_item_w( m_brush_paint , m_brush_paint_t , L"paint brush" , 200 );
	x += 3;
	create_item_w( m_brush_stroke , m_brush_stroke_t , L"stroke brush" , 200 );
	m_brush_stroke->SetColor( rgba( 0 , 0 , 0 , 255 ) );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	DrawConfigBack( (iSurfaceDest)p->m_surface , GetRect().Size() );
}

// public functions
public:
//=================================================================================================
BrushView() : m_id( 0 ) , m_es( 5 ) , m_ts( 11 )
{
}
//=================================================================================================
void SetMsgCallback
		(
		rControlMsg&		msg , 
		int					id
		)
{
	m_msg	= msg;
	m_id	= id;
}
};
/**************************************************************************************************
"Coord" class 
**************************************************************************************************/
class Coord
{
// variable member
private:
	iSubCoordLayer	m_coord;
	fvector2		m_coord_vec;
	const float		m_coord_len;
	const float		m_handle_r;
	
	// brush/pen
	iFont_gp		m_font;
	iPaint_gp		m_brush;
	iPen_gp			m_pen;
	
// public functions
public:
//=================================================================================================
Coord() : m_coord_len( 150.0f ) , m_coord_vec( 150.0f , 150.0f ) , m_handle_r( 5.0f )
{
	m_brush		= CreatePaintSolid( rgba( 0 , 0 , 0 , 255 ) );
	m_pen		= CreatePenStroke( CreateJoint( Bevel_JointType_gp ) , CreateCap( Flat_CapType_gp ) , CreateCapArrow( 4.0f , 3.5f ) );
	m_font		= CreateFont( fsize( 0.0f , 10.0f ) , L"Tahoma" , Roman_FontCharsetType );
}
//=================================================================================================
iCoordLayer SetCoord
		(
		iCoordLayer&	coord
		)
{
	m_coord			= coord->AddChild( (iCoordLayer)instance<SubCoordLayer>() );
	m_coord_vec		= fvector2( m_coord_len , m_coord_len );
	m_coord->m_unit	= unit_ip( value_ip::px , 1.0f , 1.0f );
	m_coord->m_org	= point_iplr( value_iplr::px , fvector2( 0.0f , 0.0f ) );
	return m_coord;
}
//=================================================================================================
void SetPoint
		(
		int				off , 
		const fvector2&	pnt
		)
{
	if( off == 0 || off == 1 )
	{
		Coord_ld	coord;
		if( false == m_coord->GetCoord_ld( &coord , 0 , 0 ) )
			return;
		fvector2	p = coord.PDtoL( pnt );
		m_coord_vec.m[ off ] = p.m[ off ];
		
		int		c_off , c_num = m_coord->GetChildnum();
		for( c_off = 0 ; c_off < c_num ; c_off++ )
		{
			iSubCoordLayer	c = m_coord->GetChild( c_off );
			if( c == true )
				c->m_unit	= unit_ip( value_ip::inch , 0.03937f * m_coord_vec.x / m_coord_len , 0.03937f * m_coord_vec.y / m_coord_len );
		}
	}
	else if( off == 2 )
	{
		iCoordLayer	parent = m_coord->GetParent();
		if( parent == false )
			return;
		Coord_ld	coord;
		if( false == parent->GetCoord_ld( &coord , 0 , 0 ) )
			return;
		fvector2	p	= coord.PDtoP( pnt );
		m_coord->m_org	= point_iplr( value_iplr::px , p );
	}
}
//=================================================================================================
bool Search
		(
		int*			off , 
		const fvector2&	pnt
		)
{
	Coord_ld	coord;
	if( false == m_coord->GetCoord_ld( &coord , 0 , 0 ) )
		return false;

	fvector2	p	= coord.PDtoL( pnt );
	frect		r( p.x - m_handle_r , p.y - m_handle_r , p.x + m_handle_r , p.y + m_handle_r );
	if( true == r.IsInside( fvector2( m_coord_vec.x , 0.0f ) ) )
	{
		*off	= 0;
		return true;
	}
	if( true == r.IsInside( fvector2( 0.0f , m_coord_vec.y ) ) )
	{
		*off	= 1;
		return true;
	}
	if( true == r.IsInside( fvector2( 0.0f , 0.0f ) ) )
	{
		*off	= 2;
		return true;
	}
	return false;
}
//=================================================================================================
void Draw
		(
		iGraphics_gp&	g
		)
{
	SaveAttr	save( g );
	faffine		ltod	= m_coord->LtoD();
	
	g->SetStrokePaint( m_brush );
	g->SetStrokePen( m_pen );
	g->SetStrokeWidth( 1.0f );
	g->SetStrokeClose( false );
	g->SetFont( m_font );
	
	fvector2	p[] = { -fvector2( m_coord_vec.x , 0.0f ) , fvector2( m_coord_vec.x , 0.0f ) , -fvector2( 0.0f , m_coord_vec.y ) , fvector2( 0.0f , m_coord_vec.y ) };
	g->StrokeLine( 2 , &p[0] , faffine() , ltod );
	g->StrokeLine( 2 , &p[2] , faffine() , ltod );
		
	wchar_t		buf[256];
	g->SetTextAlign( m_coord_vec.x < 0.0f ? Right_TextAlignHorz_gp : Left_TextAlignHorz_gp , Center_TextAlignVert_gp );
	cb_swprintf( buf , L"%.2f[mm]" , m_coord_vec.x / m_coord_len );
	g->DrawText( buf , wcslen( buf ) , ltod.Transform( fvector2( m_coord_vec.x + ( m_coord_vec.x < 0.0f ? -5.0f : 5.0f ) , 0.0f ) ) , rgba( 0 , 0 , 0 ) , 0 );

	g->SetTextAlign( Center_TextAlignHorz_gp , m_coord_vec.y < 0.0f ? Bottom_TextAlignVert_gp : Top_TextAlignVert_gp );
	cb_swprintf( buf , L"%.2f[mm]" , m_coord_vec.y / m_coord_len );
	g->DrawText( buf , wcslen( buf ) , ltod.Transform( fvector2( 0.0f , m_coord_vec.y + ( m_coord_vec.y < 0.0f ? -5.0f : 5.0f ) ) ) , rgba( 0 , 0 , 0 ) , 0 );
}
};
/**************************************************************************************************
"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<Control1View>			m_control1;
	instance<Control2View>			m_control2;
	instance<BrushView>				m_brush;
	instance<TimeCfgView>			m_time;
	instance<Graphics_gp>			m_graphics;

	int									m_edit_type;
	int									m_edit_pnt;
	fvector2							m_pnt[21];

	// brush/pen
	iPaint_gp							m_brush_back;
	iPaint_gp							m_brush_coord;
	iPaint_gp							m_brush_handle_dest;
	iPaint_gp							m_brush_handle_src;
	iPen_gp								m_pen_coord;
	iPaint_gp							m_brush_clip;
	iPen_gp								m_pen_handle;

	// path	
	instance<PathLogic>				m_path_dest;
	instance<Path>					m_path_src;
	instance<Path>					m_path_clip;
	
	// coord
	iDeviceCoordLayer					m_root;
	Coord								m_coord;
	iSubCoordLayer						m_coord_graphics;

	const float							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;

// private functions
private:
//=================================================================================================
int GetPointNum()
{
	return 21;
}
//=================================================================================================
fvector2 GetPoint
		(
		int				off
		)
{
	return m_pnt[off];
}
//=================================================================================================
void SetPoint
		(
		int					off , 
		const fvector2&		pnt
		)
{
	m_pnt[off] = pnt;
}	
//=================================================================================================
bool Search
		(
		const fvector2&		pnt , 
		int*				pntoff
		)
{	
	int		off , num = GetPointNum();
	for( off = 0 ; off < num ; off++ )
	{
		fvector2	p = GetPoint( off );
		frect		r( p.x - m_handle_r , p.y - m_handle_r , p.x + m_handle_r , p.y + m_handle_r );
		if( true == r.IsInside( pnt ) )
		{
			*pntoff	= off;
			return true;
		}
	}
	return false;
}
//=================================================================================================
void DrawHandleClip
		(
		const faffine&	ltod
		)
{
	m_graphics->SetStrokePaint( m_brush_clip );
	m_graphics->SetStrokePen( m_pen_handle );
	m_graphics->SetStrokeClose( true );
	m_graphics->SetStrokeWidth( 0.2f );
	m_graphics->StrokeLine( 7 , &m_pnt[14] , faffine() , ltod );

	m_graphics->SetPaint( m_brush_clip );
	int			pntoff , pntnum = GetPointNum();
	for( pntoff = 14 ; pntoff < pntnum ; pntoff++ )
	{
		m_graphics->PaintCircle( GetPoint( pntoff ) , m_handle_r , m_handle_r , ltod );
	}
}
//=================================================================================================
void DrawHandle
		(
		const faffine&	ltod
		)
{
	m_graphics->SetStrokePen( m_pen_handle );
	m_graphics->SetStrokeClose( true );
	m_graphics->SetStrokeWidth( 0.2f );

	m_graphics->SetPaint( m_brush_handle_dest );
	m_graphics->SetStrokePaint( m_brush_handle_dest );
	m_graphics->StrokeLine( 7 , &m_pnt[0] , faffine() , ltod );
	int			pntoff , pntnum = GetPointNum();
	for( pntoff = 0 ; pntoff < 7 ; pntoff++ )
	{
		m_graphics->PaintCircle( GetPoint( pntoff ) , m_handle_r , m_handle_r , ltod );
	}
	m_graphics->SetPaint( m_brush_handle_src );
	m_graphics->SetStrokePaint( m_brush_handle_src );
	m_graphics->StrokeLine( 7 , &m_pnt[7] , faffine() , ltod );
	for( ; pntoff < 14 ; pntoff++ )
	{
		m_graphics->PaintCircle( GetPoint( pntoff ) , m_handle_r , m_handle_r , ltod );
	}
	// edit handle
	m_brush->m_brush_paint->DrawEditHandle( (iGraphics_gp)m_graphics , ltod );
	m_brush->m_brush_stroke->DrawEditHandle( (iGraphics_gp)m_graphics , ltod );
}
//=================================================================================================
void SetClip
		(
		const faffine&	ltod , 
		bool			draw
		)
{
	m_path_clip->Reset();
	m_path_clip->Move( m_pnt[14] , faffine() , true );
	m_path_clip->Line( m_pnt[15] );
	m_path_clip->BezierQ( m_pnt[16] , m_pnt[17] );
	m_path_clip->BezierC( m_pnt[18] , m_pnt[19] , m_pnt[20] );
	
	// draw
	if( draw == true )
	{
		m_graphics->SetStrokePaint( m_brush_clip );
		m_graphics->SetStrokePen( m_pen_handle );
		m_graphics->SetStrokeWidth( 0.5f );
		m_graphics->SetStrokeClose( true );
		m_graphics->StrokePath( (iPathLogicInfo)m_path_clip , faffine() , ltod );
	}
	m_graphics->SetClip( (iPathLogicInfo)m_path_clip , ltod );
}
//=================================================================================================
void DrawPath
		(
		const DPI&		dpi , 
		const faffine&	ltod
		)
{
	m_path_dest->Reset();
	m_path_dest->Move( m_pnt[0] , faffine() , true );
	m_path_dest->Line( m_pnt[1] );
	m_path_dest->BezierQ( m_pnt[2] , m_pnt[3] );
	m_path_dest->BezierC( m_pnt[4] , m_pnt[5] , m_pnt[6] );

	m_path_src->Reset();
	m_path_src->Move( m_pnt[7] , faffine() , true );
	m_path_src->Line( m_pnt[8] );
	m_path_src->BezierQ( m_pnt[9] , m_pnt[10] );
	m_path_src->BezierC( m_pnt[11] , m_pnt[12] , m_pnt[13] );
	m_path_dest->Operate( m_control1->m_pathoperator->GetValue() , (iPathLogicInfo)m_path_src , faffine() );

	m_graphics->SetPaint( m_brush->m_brush_paint->GetBrush( dpi , ltod ) );
	m_graphics->SetPaintPathFillRule( m_control1->m_fillrule->GetValue() );
	m_graphics->PaintPath( (iPathLogicInfo)m_path_dest , ltod );
}
//=================================================================================================
void DrawStroke
		(
		const DPI&		dpi , 
		const faffine&	ltod
		)
{
	m_path_dest->Reset();
	m_path_dest->Move( m_pnt[0] , faffine() , m_control2->m_pen->GetClose() );
	m_path_dest->Line( m_pnt[1] );
	m_path_dest->BezierQ( m_pnt[2] , m_pnt[3] );
	m_path_dest->BezierC( m_pnt[4] , m_pnt[5] , m_pnt[6] );
	m_path_src->Reset();
	m_path_src->Move( m_pnt[7] , faffine() , m_control2->m_pen->GetClose() );
	m_path_src->Line( m_pnt[8] );
	m_path_src->BezierQ( m_pnt[9] , m_pnt[10] );
	m_path_src->BezierC( m_pnt[11] , m_pnt[12] , m_pnt[13] );
	m_path_dest->Operate( Or_PathOperator , (iPathLogicInfo)m_path_src , faffine() );
	m_graphics->SetStrokePaint( m_brush->m_brush_stroke->GetBrush( dpi , ltod ) );
	m_graphics->SetStrokePen( m_control2->m_pen->GetPen() );
	m_graphics->SetStrokeWidth( m_control2->m_pen->GetWidth() );
	m_graphics->SetStrokeClose( m_control2->m_pen->GetClose() );
	m_graphics->StrokePath( (iPathLogicInfo)m_path_dest , faffine() , ltod );
}
// callback functions
private:
//=================================================================================================
void cb_call ValueChanged_controlmsg
		(
		int		id
		)
{
	RequireUpdate( irect( ivector2( 0 , 0 ) , GetRect().Size() ) , false );
}
// msg functions
private:
//=================================================================================================
void OnCreate
		(
		Create_ViewPM*	p
		)
{
	m_control1->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( 1 , 1 ) , isize( 130 , 310 ) ) );
	m_control1->SetMsgCallback( ( rControlMsg )( reference )this_object() , 100 );

	m_control2->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( p->m_rect.xmax - 130 - 1 , 1 ) , isize( 130 , 490 ) ) );
	m_control2->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 );

	m_brush->Create( ( rViewParentCtrl )( reference )this_object() , irect( ivector2( 1 , p->m_rect.Size().height - 1 - 150 ) , isize( 415 , 150 ) ) );
	m_brush->SetMsgCallback( ( rControlMsg )( reference )this_object() , 0 );
}
//=================================================================================================
void OnUpdate
		(
		Update_ViewPM*	p
		)
{
	// set surface
	m_graphics->SetSurface( p->m_surface );
	m_root->m_dpi = p->m_surface->GetDestDPI();
	m_root->m_view= p->m_surface->GetDestSize();
	
	// back
	m_graphics->SetPaint( m_brush_back );
	m_graphics->PaintRect( 0 , faffine() );
	
	// misc
	m_graphics->SetAntialias( m_control1->m_anti->GetValue() );
	m_graphics->SetBlender( m_control1->m_blender->GetBlender() );
	m_graphics->SetAlpha( m_control1->m_alpha->GetValue() );

	// coord org
	m_coord.Draw( (iGraphics_gp)m_graphics );

	// set coord
	{
		SaveAttr	save( (iGraphics_gp)m_graphics );
		Coord_ld	coord;
		m_coord_graphics->GetCoord_ld( &coord , 0 , 0 );
		faffine		ltod	= coord.LtoPD();
		faffine		lton	= coord.GetLogical().LtoD_xy();
		DPI			dpi		= coord.GetLogical().GetDPI();//m_coord_graphics->GetDPI();	

		// clip
		if( m_control1->m_disp_state->GetClipState() == true )
			SetClip( ltod , m_control1->m_disp_state->GetHandleState() );

		// draw path
		m_time->BeginMeasure();
		if( m_control1->m_disp_state->GetPathState() == true )
			DrawPath( p->m_surface->GetDestDPI() , ltod );
		if( m_control1->m_disp_state->GetStrokeState() == true )
			DrawStroke( dpi , ltod );
		m_time->EndMeasure();

		// clip
		m_graphics->ReleaseClip();
		
		if( m_control1->m_disp_state->GetHandleState() == true && m_control1->m_disp_state->GetClipState() == true )
			DrawHandleClip( ltod );
		if( m_control1->m_disp_state->GetHandleState() == true )
			DrawHandle( ltod );
	}
	m_graphics->ReleaseSurface();
}
//=================================================================================================
void OnSize
		(
		Size_ViewPM*	p
		)
{
	m_root->m_view	= p->m_rect.Size();
	m_control2->Move( irect( ivector2( p->m_rect.xmax - 130 - 1 , 1 ) , isize( 130 , 490 ) ) );
	m_brush->Move( irect( ivector2( 1 , p->m_rect.Size().height - 150 - 1 ) , isize( 415 , 150 ) ) );
}
//=================================================================================================
void OnLDragStart
		(
		LDragStart_ViewPM*	p
		)
{
	isize	size = GetRect().Size();
	if( m_control1->m_disp_state->GetHandleState() == false )
		return;
	
	faffine	dtol = m_coord_graphics->CtoC( value_ipl::logical , value_ipl::logical , (iCoordLayer)m_root );
	if( true == m_brush->m_brush_paint->SearchEditPoint( dtol.Transform( p->m_pos ) , &m_edit_pnt ) )
	{
		m_edit_type	= 1;
		return;
	}
	if( true == m_brush->m_brush_stroke->SearchEditPoint( dtol.Transform( p->m_pos ) , &m_edit_pnt ) )
	{
		m_edit_type	= 3;
		return;
	}
	if( true == Search( dtol.Transform( p->m_pos ) , &m_edit_pnt ) )
	{
		m_edit_type	= 0;
		return;
	}
	if( true == m_coord.Search( &m_edit_pnt , p->m_pos ) )
	{
		m_edit_type = 2;
		return;
	}
}
//=================================================================================================
void OnLDrag
		(
		LDrag_ViewPM*	p
		)
{
	faffine	dtol = m_coord_graphics->CtoC( value_ipl::logical , value_ipl::logical , (iCoordLayer)m_root );

	if( m_edit_pnt == -1 )
		return;
	else if( m_edit_type == 2 )
		m_coord.SetPoint( m_edit_pnt , p->m_pos );
	else if( m_edit_type == 0 )
		SetPoint( m_edit_pnt , dtol.Transform( p->m_pos ) );
	else if( m_edit_type == 1 )
		m_brush->m_brush_paint->SetEditPoint( m_edit_pnt , dtol.Transform( p->m_pos ) );
	else if( m_edit_type == 3 )
		m_brush->m_brush_stroke->SetEditPoint( m_edit_pnt , dtol.Transform( p->m_pos ) );
	RequireUpdate( irect( ivector2( 0 , 0 ) , GetRect().Size() ) , false );
}
//=================================================================================================
void OnLDragEnd
		(
		LDragEnd_ViewPM*	p
		)
{
	m_edit_type	= -1;
	m_edit_pnt = -1;
}
//=================================================================================================
void OnLDragCancel
		(
		LDragCancel_ViewPM*	p
		)
{
	m_edit_type	= -1;
	m_edit_pnt = -1;
}
// public functions
public:
//=================================================================================================
MainView() : 
		m_handle_r( 1.0f ) , 
		m_edit_type( -1 ) , 
		m_edit_pnt( -1 ) , 
		m_hlc_dest( 40,121,121) , 
		m_hcc_dest( 40,121,121) , 
		m_hlc_src( 121,121,40) , 
		m_oc( 60 , 100 , 60 ) , 
		m_opc( 30,100,100 ) , 
		m_pc( 127 , 191 , 121 , 255 )
{
	m_brush_back		= CreatePaintSolid( rgba(255 , 255 , 235 ) );
	m_brush_coord		= CreatePaintSolid( rgba( 0 , 0 , 0 , 255 ) );
	m_brush_handle_dest	= CreatePaintSolid( rgba(121,121,40) );
	m_brush_handle_src	= CreatePaintSolid( rgba(40,121,121) );
	m_pen_coord			= CreatePenStroke( CreateJoint( Bevel_JointType_gp ) , CreateCap( Flat_CapType_gp ) , CreateCapArrow( 4.0f , 3.5f ) );
	m_brush_clip		= CreatePaintSolid( rgba(200 , 100 , 50 ) );
	m_pen_handle		= CreatePenStroke();
	
	m_root					= (iDeviceCoordLayer)instance<DeviceCoordLayer>();
	iSubCoordLayer	center	= m_root->AddChild( (iCoordLayer)instance<SubCoordLayer>() );
	center->m_unit			= unit_ip( value_ip::px , 1.0f , 1.0f );
	center->m_org			= point_iplr( value_iplr::ratio , fvector2( 0.5f , 0.4f ) );

	iCoordLayer		t		= m_coord.SetCoord( (iCoordLayer)center );
	m_coord_graphics		= t->AddChild( (iCoordLayer)instance<SubCoordLayer>() );
	m_coord_graphics->m_unit= unit_ip( value_ip::inch , 0.03937f , 0.03937f );
	m_coord_graphics->m_org	= point_iplr( value_iplr::ratio , fvector2( 0.0f , 0.0f ) );

	m_pnt[0]	= fvector2( -30.0f , 0.0f );
	m_pnt[1]	= fvector2( 0.0f , -20.0f );
	m_pnt[2]	= fvector2( 30.0f , -20.0f );
	m_pnt[3]	= fvector2( 30.0f , 0.0f );
	m_pnt[4]	= fvector2( 20.0f , 10.0f );
	m_pnt[5]	= fvector2( 10.0f , 0.0f );
	m_pnt[6]	= fvector2( 0.0f , 35.0f );

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

	m_pnt[14]	= fvector2( -25.0f , 0.0f );
	m_pnt[15]	= fvector2( -25.0f , -25.0f );
	m_pnt[16]	= fvector2( 25.0f , -25.0f );
	m_pnt[17]	= fvector2( 25.0f , 0.0f );
	m_pnt[18]	= fvector2( 25.0f , 25.0f );
	m_pnt[19]	= fvector2( 0.0f , 25.0f );
	m_pnt[20]	= fvector2( -25.0f , 25.0f );
}
//=================================================================================================
bool Initialize
		(
		const wstring&	folder
		)
{
	wstring		material;
	if( 0xFFFFFFFF == GetFileAttributesW( ( folder + L"../../../../material" ).c_str() ) )
		material = folder + L"material/";
	else
		material = folder + L"../../../../material/";

	int		off;
	for( off = 0 ; off < 4 ; off++ )
	{
		wchar_t		path[ 256 ];
		cb_swprintf( path , L"tex%d.psd" , off );
		if( false == m_brush->m_brush_paint->AddTexture( material + path ) )
		{
			MessageBox( wstring( L"can't open file: " ) + path , L"error" );
			return false;
		}
		if( false == m_brush->m_brush_stroke->AddTexture( material + path ) )
		{
			MessageBox( wstring( L"can't open file: " ) + path , L"error" );
			return false;
		}
	}
	return true;
}
};

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

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





