/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2017/02/01
/// 
/// @brief  GUC基本コンポーネント。
/// 
/// ****************************************************************************



#include "CPL_GUC_FrameEvent.h"
//#include "CPL_GUC_Component.h"
#include "../DX/CPL_DX_SamplerState.h"
#include "../DX/CPL_DX_BlendState.h"
#include "../DX/CPL_DX_DepthStencilState.h"


namespace CPL {
namespace GUC {


// _____________________________________________________________________________
/// @brief コンポーネント標準背景カラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Component::GetDefaultColor_CompBG()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::StaticBG()
        );
  return sp_color;
}

// _____________________________________________________________________________
/// @brief コンポーネント標準フレームカラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Component::GetDefaultColor_CompFrame()
{
  static auto
    sp_color = 
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::StaticFrame()
        );
  return sp_color;
}

// _____________________________________________________________________________
/// @brief デフォルトテキストカラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Component::GetDefaultColor_CompText()
{
  static DX::RectColor4P
    gradiate
      ( DX::ColorType(1.0f, 1.0f, 1.0f, 0.8f)
      , DX::ColorType(0.9f, 0.9f, 0.9f, 0.8f)
      , DX::ColorType(0.8f, 0.8f, 0.8f, 0.8f)
      , DX::ColorType(0.9f, 0.9f, 0.9f, 0.8f)
      );
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::StaticText()
        );
  return sp_color;
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 静的パラメータ群　コンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component::zzo_static_param::zzo_static_param()
  : id_bank( 0, 1000000, 32*Ki )
  , ptr_d3ddev( nullptr )
  , line_height( 20 )
  , all_applied_draw_alpha( 1.0f )
//  , draw_ID( 0 )
{
}




// _____________________________________________________________________________
/// @brief コンポーネント間の座標変換
/// 
/// @param[in] in_sp_comp_from
///   : 変換前の座標系となるコンポーネントを指すスマートポインタを指定します。
/// @param[in] in_sp_comp_to
///   : 変換先の座標系となるコンポーネントを指すスマートポインタを指定します。
/// @param[in,out] io_array_for_vector
///   : 変換するベクトルの配列を指定します。
/// @param[in] in_table_num
///   : 変換ベクトル配列の要素数を指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::MappingPosition
    ( _in<sdptr<Component>> in_sp_comp_from
    , _in<sdptr<Component>> in_sp_comp_to
    , pio<float2          > io_array_for_vector
    , _in<int             > in_table_num
    )
{
  if( in_sp_comp_from == in_sp_comp_to )
  {
    return;
  }

  float2 offs(0,0);

  // スクリーン空間からクライアント空間への変換の場合
  if( in_sp_comp_from == nullptr )
  {
    auto sp_comp = in_sp_comp_to;
    
    while( sp_comp )
    {
      offs += sp_comp->GetPosition();

      sp_comp = sp_comp->GetBelongComponent( eParentType::Position );
    }
    
    // 
    for( int i = 0; i < in_table_num; ++i )
    {
      io_array_for_vector[ i ] -= offs;
    }
  }

  // クライアント空間からスクリーン空間への変換の場合
  else
  if( in_sp_comp_to == nullptr )
  {
    auto sp_comp = in_sp_comp_from;
    
    while( sp_comp )
    {
      offs += sp_comp->GetPosition();

      sp_comp = sp_comp->GetBelongComponent( eParentType::Position );
    }
    
    // 
    for( int i = 0; i < in_table_num; ++i )
    {
      io_array_for_vector[ i ] += offs;
    }
  }

  // ***** 以下の親子判定は、親子関係パターンが複数になったことで意味をなさなくなった *****
  //// in_sp_comp_from が in_sp_comp_to の親の場合（子供空間への変換）
  //else
  //if( in_sp_comp_from->CheckLinkDownClass( in_sp_comp_to ) )
  //{
  //  auto sp_comp = in_sp_comp_to;
  //  
  //  while( sp_comp  &&  sp_comp != in_sp_comp_from )
  //  {
  //    offs += sp_comp->GetPosition();

  //    sp_comp = sp_comp->GetBelongComponent( eParentType::Position );
  //  }
  //  if( sp_comp == nullptr ) // ルートまで達した場合、ルートから逆算
  //  {
  //    MappingPosition( nullptr, in_sp_comp_to, io_vec_table, in_table_num );
  //  }
  //  
  //  // 
  //  for( int i = 0; i < in_table_num; ++i )
  //  {
  //    io_vec_table[ i ] -= offs;
  //  }
  //}

  //// in_sp_comp_from が in_sp_comp_to の子供の場合（親空間への変換）
  //else
  //if( in_sp_comp_from->CheckLinkUpClass( in_sp_comp_to ) )
  //{
  //  auto sp_comp = in_sp_comp_from;
  //  
  //  while( sp_comp  &&  sp_comp != in_sp_comp_to )
  //  {
  //    offs += sp_comp->GetPosition();

  //    sp_comp = sp_comp->GetBelongComponent( eParentType::Position );
  //  }
  //  // ルートに達してしまった場合
  //  if( sp_comp == nullptr )
  //  {
  //    MappingPosition( nullptr, in_sp_comp_from, io_vec_table, in_table_num );
  //  }
  //  
  //  // 
  //  for( int i = 0; i < in_table_num; ++i )
  //  {
  //    io_vec_table[ i ] += offs;
  //  }
  //}

  // in_sp_comp_from と in_sp_comp_to が直系でない場合
  else
  {
    // 一度スクリーン空間に変換後、対象の空間へ
    MappingPosition( in_sp_comp_from, nullptr, io_array_for_vector, in_table_num );
    MappingPosition( nullptr, in_sp_comp_to, io_array_for_vector, in_table_num );
  }

}



/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 初期設定
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::zzf_setupInitialize_()
{
  // static parameter initialized
  static bool f_static_init = 
    zzf_setupStaticInitialize_();

  try {
    // local parameter initialized
    m_comp_ID = sm_comp_id_bank().GetNewID();
    SetAutoUserID();
    m_sp_sparam = sm_param();

    // ID
    if( sm_comp_table().size() <= m_comp_ID )
    {
      sm_comp_table().resize( static_cast<U32>(m_comp_ID * 1.2) + 8 );
    }
    sm_comp_table()[ m_comp_ID ] = this;

    if( !f_static_init )
    {
      return false;
    }

    // 基本パーツテクスチャの読み込み
    if( sm_ptr_d3ddev()  &&  sm_tex_parts() == nullptr )
    {
#ifdef CPL_USE_DX11ex
      DirectX::CreateWICTextureFromMemory
        ( DX::Graphics::GetDevice()
        , Image_Parts
        , Image_Parts_Size
        , nullptr
        , &sm_tex_parts()
        );
#else
      ID3D11Resource* ptr_dx_resource;
      D3DX11CreateTextureFromMemory
        ( DX::Graphics::GetDevice()
        , Image_Parts
        , Image_Parts_Size
        , nullptr
        , nullptr
        , &ptr_dx_resource
        , nullptr
        );
      // シェーダーリソースビューの作成
      DX::Graphics::GetDevice()->CreateShaderResourceView(
        ptr_dx_resource, nullptr, &sm_tex_parts() );

      ptr_dx_resource->Release(); // SRVが保持しているので、OK
#endif
    }
  }
  catch(...)
  {
    CPL_BREAK(true);
  }

  return true;
}
/// @endcond

// _____________________________________________________________________________
/// @brief 作成時イベント　カラー設定
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::On_Create()
{
  // デフォルトカラー
  SetColorParameterBG   ( GetDefaultColor_BG()    );
  SetColorParameterFrame( GetDefaultColor_Frame() );
  SetColorParameterText ( GetDefaultColor_Text()  );

  return true;
}


/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 静的初期化関数
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::zzf_setupStaticInitialize_()
{
  sm_sp_RC_polygon() = CPL_MAKE_SHARED(DX::RenderCollection);
  
  // レイアウトバッファ ※ 一度だけ処理するために、↓のようなことをしている。
  static sdptr<DX::Layout::Buffer>
    sp_poly_layout_buf =
    sm_sp_layout_buf() =
      CPL_MAKE_SHARED
        ( DX::Layout::Buffer
        , DX::Layout::VtxElmXYZW() + DX::Layout::VtxElmDiffuse()
        );

  // シェーダーコードフラグメント（ＶＳ）
  static DX::Shader::CodeFragmentCollection
    vs_code_frgm_collection =
      DX::Shader::VSF::VertexLayout( *sp_poly_layout_buf ) +
      DX::Shader::VSF::ImmediateInputPositionT(0) +
      DX::Shader::VSF::ImmediateInputColor(0,0);
  // 頂点シェーダコード
  static char_cptr vs_func_name = "VS_Main";
  static DX::Shader::VSCode
    vsc( vs_func_name, vs_code_frgm_collection );
  // 頂点シェーダー
  static sdptr<DX::Shader::VertexShader>
    sp_VS_polygon =
      CPL_MAKE_SHARED( DX::Shader::VertexShader, vsc, vs_func_name );

  // シェーダーコードフラグメント（ＰＳ）
  static DX::Shader::CodeFragmentCollection
    ps_code_frgm_collection =
      DX::Shader::PSF::Input_SV_Position() +
      DX::Shader::PSF::ImmediateInputColor();
  // ピクセルシェーダコード
  static char_cptr ps_func_name = "PS_Main";
  static DX::Shader::PSCode
    psc( ps_func_name, ps_code_frgm_collection );
  // ピクセルシェーダ
  static sdptr<DX::Shader::PixelShader>
    sp_PS_polygon =
      CPL_MAKE_SHARED( DX::Shader::PixelShader, psc, ps_func_name );

  // インプットレイアウト
  static sdptr<DX::Layout::Input>
    sp_poly_input_layout =
      CPL_MAKE_SHARED
        ( DX::Layout::Input
        , *sp_poly_layout_buf
        , sp_VS_polygon->GetDXBlob()
        );

  // 頂点バッファ
  sdptr<DX::Buffer::DynamicEX_Vertex>
    sp_VB =
      CPL_MAKE_SHARED( DX::Buffer::DynamicEX_Vertex, 0 );

  // インデックスバッファの作成
  sdptr<DX::Buffer::DynamicEX_Index>
    sp_IB =
      CPL_MAKE_SHARED( DX::Buffer::DynamicEX_Index, 0 );
  
  // サンプラ設定
  DX::DX_SAMPLER_DESC desc_SS;
  memset( &desc_SS, 0, sizeof(desc_SS) );
  desc_SS.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  desc_SS.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
  desc_SS.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
  desc_SS.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
  desc_SS.ComparisonFunc = D3D11_COMPARISON_NEVER;
  desc_SS.MinLOD = 0;
  desc_SS.MaxLOD = D3D11_FLOAT32_MAX;
  sdptr<DX::SamplerState> sp_SS;
  sp_SS = CPL_MAKE_SHARED( DX::SamplerState, desc_SS );
  // 描画指示
  //DrawIndexedOperator::SpLinked sp_DIO( new DrawIndexedOperator() );
  //sp_DIO->SetPrimType( D3DPT_TRIANGLELIST );

  // ラスタライザ設定
  DX::DX_RASTERIZER_DESC desc_RS = {
    D3D11_FILL_SOLID, // D3D11_FILL_MODE FillMode;
    D3D11_CULL_NONE,  // D3D11_CULL_MODE CullMode;
    true, // BOOL FrontCounterClockwise;
    0, // INT DepthBias;
    0, // FLOAT DepthBiasClamp;
    0, // FLOAT SlopeScaledDepthBias;
    true, // BOOL DepthClipEnable;
    false, // BOOL ScissorEnable;
    false, // BOOL MultisampleEnable;
    true //BOOL AntialiasedLineEnable;
  };
  sdptr<DX::RasterizerState>
    sp_RS = CPL_MAKE_SHARED( DX::RasterizerState, desc_RS );

  // ブレンド設定
  DX::DX_BLEND_DESC desc_BS;
  desc_BS.AlphaToCoverageEnable  = FALSE;
  desc_BS.IndependentBlendEnable = FALSE;
  desc_BS.RenderTarget[0].BlendEnable = true;
  desc_BS.RenderTarget[0].SrcBlend  = D3D11_BLEND_SRC_ALPHA;
  desc_BS.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
  desc_BS.RenderTarget[0].BlendOp   = D3D11_BLEND_OP_ADD;
  desc_BS.RenderTarget[0].SrcBlendAlpha  = D3D11_BLEND_SRC_ALPHA;
  desc_BS.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ONE;
  desc_BS.RenderTarget[0].BlendOpAlpha   = D3D11_BLEND_OP_ADD;
  desc_BS.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
  sdptr<DX::BlendState>
    sp_BS = CPL_MAKE_SHARED( DX::BlendState, desc_BS );

  // デプスステンシルステートの作成
  DX::DX_DEPTH_STENCIL_DESC desc_ds = {
    TRUE, // BOOL DepthEnable;
    D3D11_DEPTH_WRITE_MASK_ALL, //D3D11_DEPTH_WRITE_MASK DepthWriteMask;
    D3D11_COMPARISON_LESS_EQUAL, // D3D11_COMPARISON_FUNC DepthFunc;
    FALSE, // BOOL StencilEnable;
    D3D11_DEFAULT_STENCIL_READ_MASK, // UINT8 StencilReadMask;
    D3D11_DEFAULT_STENCIL_WRITE_MASK, // UINT8 StencilWriteMask;
    {D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_COMPARISON_ALWAYS},// D3D11_DEPTH_STENCILOP_DESC FrontFace;
    {D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_STENCIL_OP_KEEP,D3D11_COMPARISON_ALWAYS},//D3D11_DEPTH_STENCILOP_DESC BackFace;
  };
  sdptr<DX::DepthStencilState>
    sp_DSS = CPL_MAKE_SHARED( DX::DepthStencilState, desc_ds );


  // レンダーコレクションの設定
  (*sm_sp_RC_polygon())
    << sp_poly_input_layout // 入力レイアウト
    << sp_VB                // 頂点バッファマネージャ
    << sp_IB                // インデックスバッファ
    << sp_SS                // サンプラーステート
    << sp_RS                // レンダーステート
    << sp_BS                // ブレンドステート
    << sp_DSS               // 深度ステンシルステート
    << sp_VS_polygon        // 頂点シェーダー
    << sp_PS_polygon;       // ピクセルシェーダ

  // 頂点サイズを頂点レイアウトから設定
  //sm_sp_RC_polygon()
  //  ->GetVertexBufferManager()
  //    ->SetupVertexSize_by_Declaration( sp_VL_polygon );

  return true;
}
/// @endcond


// _____________________________________________________________________________
/// @brief コンストラクタ（ルートレイヤー用）
/// 
/// @param[in] in_ptr_win_subject
///   : 親となるウィンドウクラスのアドレスを指定します。
/// @copydoc doxycomment::arg_in_position_for_component
/// @copydoc doxycomment::arg_in_size_for_component
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component::Component
( _in<WIN::Component*> in_ptr_win_subject
, _in<float2         > in_position_for_component
, _in<float2         > in_size_for_component
) : m_ptr_win_subject  ( in_ptr_win_subject )
  , m_def_cursor       ( nullptr )
  , m_frame_width      ( 1 )
  , m_flag_visible     ( true  )
  , m_flag_draw_owner  ( false )
  , m_flag_enable      ( true  )
  , m_flag_update      ( true  )
  , m_flag_draw_bg     ( true  )
  , m_flag_draw_frame  ( true  )
  , m_flag_draw_client ( true  )
  , m_initialized_level( false )
  , m_flag_clip_child  ( false )
  , m_flag_throw_mouse ( false )
{

  if( !zzf_setupInitialize_() )
  {
    return;
  }
  
  if( !dynamic_cast<FrameEvent*>(in_ptr_win_subject) )
  {
    CPL_THROW( "ウィンドウポインタはFrameEventもしくはその派生型でないといけません。" );
  }


  m_rect.x = in_position_for_component.x;
  m_rect.y = in_position_for_component.y;
  m_rect.z = (in_size_for_component.x>0.0f)
    ? m_rect.x + in_size_for_component.x
    : m_rect.x + 20;
  m_rect.w = (in_size_for_component.y>0.0f)
    ? m_rect.y + in_size_for_component.y
    : m_rect.y + 20;

  zzf_SetInitializedLevel( zzf_GetClassLevel() );
}


// _____________________________________________________________________________
/// @brief コンストラクタ（アイテムウィンドウ作成用）
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @copydoc doxycomment::arg_in_position_for_component
/// @copydoc doxycomment::arg_in_size_for_component
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component::Component
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<float2          > in_position_for_component
, _in<float2          > in_size_for_component
) : m_ptr_win_subject  ( in_sp_component_for_parent->GetSubjectWindow() )
  , m_def_cursor       ( nullptr )
  , m_frame_width      ( 1 )
  , m_flag_visible     ( true  )
  , m_flag_draw_owner  ( false )
  , m_flag_enable      ( true  )
  , m_flag_update      ( true  )
  , m_flag_draw_bg     ( true  )
  , m_flag_draw_frame  ( true  )
  , m_flag_draw_client ( true  )
  , m_initialized_level( false )
  , m_flag_clip_child  ( false )
  , m_flag_throw_mouse ( false )
  , m_wp_comp_belong   ( in_sp_component_for_parent )
  , m_rect
    { in_position_for_component.x
    , in_position_for_component.y
    , (in_size_for_component.x>0.0f) ? in_size_for_component.x : 1
    , (in_size_for_component.y>0.0f) ? in_size_for_component.y : 1
    }
{
  m_rect.z += m_rect.x;
  m_rect.w += m_rect.y;

  auto flag_create = Core::BaseFactory::GetCreating();
  if( flag_create == 0 )
  {
    CPL_THROW
      ( "ファクトリ以外からコンストラクタが呼ばれました。"
        "GUCコンポーネントは、ファクトリで生成する必要があります。"
      );
  }

  //
  zzf_setupInitialize_();

  // ノードへ追加
  // ※ 一度、実スマートポインタに渡してからノードに登録すれば、インスタンスが保持される
#ifdef CPL_DBGSW_ALLOCATOR
  sdptr<Component> sp_this( this, Core::Memory::CustomDelete<Component> );
#else
  sdptr<Component> sp_this( this );
#endif
  this->SetLinkMyself( sp_this );
  sdptr<Component> sp_comp_parent( m_wp_comp_belong.lock() ); // コンストラクタでm_wp_comp_belongに設定しておく。
  if( auto sp_comp_master = std::dynamic_pointer_cast<MasterLayer>(sp_comp_parent) )
  {
    if( auto sp_comp_downer = sp_comp_master->GetComponent_for_DrawingOwner() )
    {
      sp_comp_parent = sp_comp_downer;
    }
  }
  //else
  //if( auto sp_comp_owner = std::dynamic_pointer_cast<Owner>(in_sp_component_for_parent) )
  //{
  //  sp_comp_parent_render = sp_comp_owner->GetComponent_ClientLayer();
  //}
  sp_comp_parent->AddLinkChild( sp_this );
  
  zzf_SetInitializedLevel( zzf_GetClassLevel() );
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component::Component( cref<Component> in_component )
  : m_ptr_win_subject  ( in_component.GetSubjectWindow()  )
  , m_def_cursor       ( in_component.m_def_cursor        )
  , m_frame_width      ( in_component.m_frame_width       )
  , m_flag_visible     ( in_component.m_flag_visible      )
  , m_flag_draw_owner  ( in_component.m_flag_draw_owner   )
  , m_flag_enable      ( in_component.m_flag_enable       )
  , m_flag_update      ( in_component.m_flag_update       )
  , m_flag_draw_bg     ( in_component.m_flag_draw_bg      )
  , m_flag_draw_frame  ( in_component.m_flag_draw_frame   )
  , m_flag_draw_client ( in_component.m_flag_draw_client  )
  , m_initialized_level( in_component.m_initialized_level )
  , m_flag_clip_child  ( in_component.m_flag_clip_child   )
  , m_flag_throw_mouse ( in_component.m_flag_throw_mouse  )
  , m_wp_comp_belong   ( in_component.m_wp_comp_belong    )
  , m_rect             ( in_component.m_rect              )
{
  auto flag_create = Core::BaseFactory::GetCreating();
  if( flag_create == 0 )
  {
    CPL_THROW
      ( "ファクトリ以外からコンストラクタが呼ばれました。"
        "GUCコンポーネントは、ファクトリで生成する必要があります。"
      );
  }

  zzf_setupInitialize_();
  // zzf_setupInitialize_()でユーザーIDが設定されるが、ユーザーIDはコピー元と同じにしておく。
  m_user_ID = in_component.m_user_ID;

  // ノードへ追加
  // ※ 一度、実スマートポインタに渡してからノードに登録すれば、インスタンスが保持される
#ifdef CPL_DBGSW_ALLOCATOR
  sdptr<Component> sp_this( this, Core::Memory::CustomDelete<Component> );
#else
  sdptr<Component> sp_this( this );
#endif
  this->SetLinkMyself( sp_this );
  sdptr<Component> sp_comp_parent( m_wp_comp_belong.lock() ); // コンストラクタでm_wp_comp_belongに設定しておく。
  if( auto sp_comp_master = std::dynamic_pointer_cast<MasterLayer>(sp_comp_parent) )
  {
    if( auto sp_comp_downer = sp_comp_master->GetComponent_for_DrawingOwner() )
    {
      sp_comp_parent = sp_comp_downer;
    }
  }

  sp_comp_parent->AddLinkChild( sp_this );
}


// _____________________________________________________________________________
/// @brief デストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component::~Component()
{
  auto sp_this = GetLinkMyself();

  if( sm_sp_capture() == sp_this )
  {
    sm_sp_capture( nullptr );
  }
  if( sm_sp_focus() == sp_this )
  {
    sm_sp_focus( nullptr );
  }
//  if( sm_ptr_desktop() == this )
//  {
//    sm_ptr_desktop() = nullptr;
//  }

  //
  auto  id_comp  = GetComponentID();
  auto& tbl_comp = sm_comp_table();
  tbl_comp[ id_comp ] = nullptr;
  sm_comp_id_bank().ReleaseID( id_comp );
}


// _____________________________________________________________________________
/// @brief 座標（io_X,io_Y）がコンポーネントの矩形内に入っているかどうかを取得
/// 
/// @param[in] io_X
///   : 比較する親基点のｘ座標を指定します。\n
///   : ヒットした場合、そのコンポーネントの相対座標に変換されます。
/// @param[in] io_Y
///   : 比較する親基点のｙ座標を指定します。\n
///   : ヒットした場合、そのコンポーネントの相対座標に変換されます。
/// 
/// @retval true  : 矩形内。
/// @retval false : 矩形外。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::IsHit( rio<float> io_X, rio<float> io_Y ) const noexcept
{
  if( IsThrowMouse() )
  {
    return false;
  }
  
  float2 xy{ io_X, io_Y };
  auto sp_comp_parent = GetLinkParent();
  auto sp_comp_belong = GetBelongComponent( eParentType::Position );
  if( sp_comp_parent != sp_comp_belong )
  {
    MappingPosition( sp_comp_parent, sp_comp_belong, &xy, 1 );
  }

  if( m_rect.IsHit( xy.x, xy.y ) )
  {
    io_X = xy.x - m_rect.x;
    io_Y = xy.y - m_rect.y;
    return true;
  }
  return false;
}


// _____________________________________________________________________________
/// @brief 指定した座標（io_X,io_Y）とヒットする子供コンポーネントを取得
/// 
/// @param[in] io_X
///   : 比較する親基点のｘ座標を指定します。\n
///   : ヒットした場合、そのコンポーネントの相対座標に変換されます。
/// @param[in] io_Y
///   : 比較する親基点のｙ座標を指定します。\n
///   : ヒットした場合、そのコンポーネントの相対座標に変換されます。
/// 
/// @return ヒットしたコンポーネントのスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Component::IsHitChild( rio<float> io_X, rio<float> io_Y ) const noexcept
{
  auto sp_comp_child = GetLinkChild();
  if( sp_comp_child )
  {
    sp_comp_child = sp_comp_child->GetLinkEnd();
  }
  else
  {
    return nullptr;
  }

  // 描画オーナーの場合、自身とヒットしない場合は子供もヒットしない。
  if( this->IsDrawOwner()  &&  !GetRectCoord().IsHit( io_X, io_Y ) )
  {
    return nullptr;
  }

  // 子供チェック用座標。
  // 自身からの相対座標になるよう補正する。
  float2 xy{ io_X, io_Y };
  auto sp_comp_parent = GetLinkParent();
  auto sp_comp_belong = GetBelongComponent( eParentType::Position );
  if( sp_comp_parent != sp_comp_belong )
  {
    MappingPosition( sp_comp_parent, sp_comp_belong, &xy, 1 );
    //MappingPosition( sp_comp_parent_render, nullptr, &xy, 1 );
    //MappingPosition( nullptr, sp_comp_belong, &xy, 1 );
  }
  xy.x -= m_rect.x;
  xy.y -= m_rect.y;

  // 当たり判定。
  while( sp_comp_child )
  {
    if( sp_comp_child->IsVisible() )
    {
      if( auto sp_comp_hit = sp_comp_child->IsHitChild( xy.x, xy.y ) )
      {
        io_X = xy.x;
        io_Y = xy.y;
        return sp_comp_hit;
      }
      else
      if( sp_comp_child->IsHit( xy.x, xy.y ) )
      {
        io_X = xy.x;
        io_Y = xy.y;
        return sp_comp_child;
      }
    }
    sp_comp_child = sp_comp_child->GetLinkPrev();
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 描画オーナーウィンドウの取得
/// 
/// @return 描画オーナーウィンドウを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component> Component::GetOwnerWindow() const noexcept
{
  return FindComponent_ofType_forUpperClass<RenderOwner>();
}


//// _____________________________________________________________________________
///// @brief 描画オーナーウィンドウの取得。
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//sdptr<Component> Component::GetDrawOwnerWindow() const noexcept
//{
//  auto sp_comp = GetLinkMyself();
//
//  while( sp_comp )
//  {
//    if( sp_comp->IsDrawOwner() )
//    {
//      return sp_comp;
//    }
//
//    sp_comp = sp_comp->GetBelongComponent( eParentType::Render );
//  }
//
//  // nullptrが返る
//  return sp_comp;
//}


//// _____________________________________________________________________________
///// @brief 配置オーナーウィンドウの取得。
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//sdptr<Component> Component::GetArrangeOwnerWindow() const noexcept
//{
//  auto sp_comp = GetLinkMyself();
//
//  while( sp_comp )
//  {
//    if( sp_comp->IsArrangeOwner() )
//    {
//      return sp_comp;
//    }
//
//    sp_comp = sp_comp->GetBelongComponent( eParentType::Position );
//  }
//
//  // nullptrが返る
//  return sp_comp;
//}



// _____________________________________________________________________________
/// @brief タイマー設定
/// 
/// @param[in] in_timer_ID : タイマーIDを指定します。
/// @param[in] in_time_interval : タイマー間隔（ms単位）を指定します。
/// 
/// @return 作成されたタイマーＩＤが返ります。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
U32 Component::SetTimer( _in<U16> in_timer_ID, _in<U32> in_time_interval ) noexcept
{
  U32 timer_ID = (GetComponentID() << 16) + in_timer_ID;

  UINT_PTR ret =
    ::SetTimer
      ( GetSubjectWindow()->GetWindowHandle()
      , timer_ID
      , in_time_interval
      , nullptr
      );

  return timer_ID;
}


// _____________________________________________________________________________
/// @brief タイマー削除
/// 
/// @param[in] in_timer_ID : 削除するタイマーのIDを指定します。
/// 
/// @retval true  : 成功
/// @retval false : 失敗
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::KillTimer( _in<U16> in_timer_ID ) noexcept
{
  U32 timer_ID = (GetComponentID() << 16) + in_timer_ID;

  return ::KillTimer( GetSubjectWindow()->GetWindowHandle(), timer_ID ) != 0;
}


// _____________________________________________________________________________
/// @brief 自動調整サイズの取得
/// 
/// @param[in] in_flag_show
///   : 表示フラグを指定します。\n
///   : true  - 非表示コンポーネントも含めて計算する。\n
///   : false - 現在表示されているコンポーネントのみで計算する。
/// 
/// @return 計算されたサイズを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2
  Component::GetAdjustSize( _in<BOOL> in_flag_show ) const noexcept
{
  if( in_flag_show  ||  IsVisible() )
  {
    return float2(m_rect.Width(), m_rect.Height());
  }
  else
  {
    return float2(0,0);
  }
}

// _____________________________________________________________________________
/// @brief サイズの自動調整
/// 
/// @param[in] in_offs_size
///   : 調整時、余分に確保する値。余白。
/// @param[in] in_flag_show
///   : 非表示のコンポーネントを含めるかどうか。\n
///   : true  - 非表示コンポーネントも含め調整する。\n
///   : false - 非表示コンポーネントは含めず調整する。
/// 
/// @retval true  : サイズ変更有り。
/// @retval false : サイズ変更無し。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::AdjustSize( _in<float2> in_offs_size, _in<BOOL> in_flag_show )
{
  auto size_adj = GetAdjustSize( in_flag_show );
  return SetSize( size_adj + in_offs_size );
}


// _____________________________________________________________________________-
/// コンポーネントの表示状態を設定。
/// 
/// @param[in] in_flag_visible
///   : 表示の有無を設定。\n
///   : true  - 表示。\n
///   : false - 非表示。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetStateVisible( _in<bool> in_flag_visible ) noexcept
{
  if( m_flag_visible != in_flag_visible )
  {
    m_flag_visible = in_flag_visible;

    call_On_Show( this->GetLinkMyself(), m_flag_visible );

    Update();
  }
}


// _____________________________________________________________________________
/// @brief コンポーネントのマウスイベント有効状態を設定。
/// 
/// @param[in] in_flag_enable
///   : 有効・無効を設定。\n
///   : true  - 有効。\n
///   : false - 無効。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetStateEnable( _in<bool> in_flag_enable ) noexcept
{
  if( m_flag_enable != in_flag_enable )
  {
    m_flag_enable = in_flag_enable;

    Update();
  }
}


// _____________________________________________________________________________
/// @brief 背景描画設定。
/// 
/// @param[in] in_flag_draw_bg
///   : 背景を描画するかどうか。\n
///   : true  - 描画する。\n
///   : false - 描画しない。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetStateDrawBG( _in<bool> in_flag_draw_bg ) noexcept
{
  if( m_flag_draw_bg != in_flag_draw_bg )
  {
    m_flag_draw_bg = (in_flag_draw_bg != 0);

    Update();
  }
}


// _____________________________________________________________________________
/// @brief 枠描画設定。
/// 
/// @param[in] in_flag_draw_frame
///   : 枠を描画するかどうか。\n
///   : true  - 描画する。\n
///   : false - 描画しない。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetStateDrawFrame( _in<bool> in_flag_draw_frame ) noexcept
{
  if( m_flag_draw_frame != in_flag_draw_frame )
  {
    m_flag_draw_frame = (in_flag_draw_frame != 0);

    Update();
  }
}


// _____________________________________________________________________________
/// @brief クライアント描画設定。
/// 
/// @param[in] in_flag_draw_client
///   : クライアント描画コールバック関数をコールするかどうか。\n
///   : true  - 描画する。\n
///   : false - 描画しない。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetStateDrawClient( _in<bool> in_flag_draw_client ) noexcept
{
  if( m_flag_draw_client != in_flag_draw_client )
  {
    m_flag_draw_client = (in_flag_draw_client != 0);

    Update();
  }
}

// _____________________________________________________________________________
/// @brief 枠の幅を設定
///
/// @param[in] in_frame_width
///   : フレームの幅を指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetFrameWidth( _in<float> in_frame_width ) noexcept
{
  m_frame_width = in_frame_width;
  if( IsDrawFrame() )
  {
    Update();
  }
}

// _____________________________________________________________________________
/// @brief 属するコンポーネントの設定
/// 
/// @param[in,out] io_sp_comp_belong
///   : 位置計算上の親コンポーネントへのスマートポインタを指定します。
/// @param[in] in_type_parent
///   : 親となるコンポーネントのタイプを指定します。\n
///   : 詳細はeParentTypeを参照してください。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::SetBelongComponent
    ( _in<sdptr<Component>> io_sp_comp_belong
    , _in<eParentType     > in_type_parent
    ) noexcept
{
  if( io_sp_comp_belong == this->GetLinkMyself() )
  {
    return;
  }

  if( in_type_parent & eParentType::Position )
  {
    m_wp_comp_belong = io_sp_comp_belong;
  }
  if( in_type_parent & eParentType::Render )
  {
    io_sp_comp_belong->AddLinkChild( GetLinkMyself() );
  }
}


// _____________________________________________________________________________
/// @brief 更新フラグの設定とウィンドウの再描画
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::Update()
{
  m_flag_update = true;

  if( auto sp_comp_parent = GetLinkParent() )
  {
    sp_comp_parent->Update();
  }
  else
  {
    UpdateSubjectWindow();
  }
}


// _____________________________________________________________________________
/// @brief 全てのウィンドウコンテナの更新フラグの設定とウィンドウの再描画
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::UpdateAllWindow()
{
  auto sp_comp = GetLinkRoot();
  while( sp_comp )
  {
    sp_comp->Update();
    sp_comp = sp_comp->GetLinkNextAll();
  }
}


// _____________________________________________________________________________
/// @brief 属する大元のウィンドウの更新
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::UpdateSubjectWindow()
{
  //SendFrameMessage
  //  ( eID::UpdateWindowBuffer
  //  , 0
  //  , reinterpret_cast<LPARAM>(this)
  //  );
  //CPL_OUTPUT( SwS("UpdateSubjectWindow\n") );

  if( auto ptr_frame = dynamic_cast<GUC::FrameEvent*>(this->GetSubjectWindow()) )
  {
    //ptr_frame->zzf_UpdateWindowBuffer();
    ptr_frame->Update();
  }
}


// _____________________________________________________________________________
/// @brief 親コンポーネントへのメッセージ通知
/// 
/// @param[in] in_sp_component : メッセージ発信元のコンポーネントを指定します。
/// @param[in] in_msg         : メッセージIDを指定します。
/// @param[in] in_wparam      : WPARAM値を指定します。
/// @param[in] in_lparam      : LPARAM値を指定します。
/// @param[in] in_type_parent : メッセージを送る親を指定します。
/// 
/// @return メッセージを送った親の数を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size_t
  Component::SendParentMessage
    ( _in<sdptr<Component>> in_sp_component
    , _in<long            > in_msg
    , _in<WPARAM          > in_wparam
    , _in<LPARAM          > in_lparam
    , _in<eParentType     > in_type_parent
    )
{
  if( in_type_parent == 0 )
  {
    return 0;
  }

  std::vector<sdptr<Component>> comp_list;
  GetBelongComponent( in_type_parent, comp_list );

  if( comp_list.empty() )
  {
    return 0;
  }

  for( auto sp_comp_belong : comp_list )
  {
    while( sp_comp_belong )
    {
      auto res =
        sp_comp_belong->On_UserProc
          ( in_sp_component
          , in_msg
          , in_wparam
          , in_lparam
          );
      if( res )
      {
        sp_comp_belong =
          sp_comp_belong->GetBelongComponent( eParentType::Position );
        if( sp_comp_belong == nullptr )
        {
          SendFrameMessage( in_msg, in_wparam, in_lparam );
        }
      }
      else
      {
        break;
      }
    }
  }

  return comp_list.size();
}

// _____________________________________________________________________________
/// @brief ルートフレームコンポーネントへのメッセージ通知。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::SendFrameMessage
    ( _in<long  > in_msg
    , _in<WPARAM> in_wparam
    , _in<LPARAM> in_lparam
    )
{
  if( m_ptr_win_subject )
  {
    ::SendMessage( m_ptr_win_subject->GetWindowHandle(), in_msg, in_wparam, in_lparam );
  }
}


// _____________________________________________________________________________
/// @brief 指定したコンポーネントに自身が属しているかチェック
/// 
/// @param[in] in_sp_component_for_parent
///   : 指定したコンポーネントに自身が属しているかチェックします。
/// @param[in] in_flag_parent
///   : 属する親のタイプを指定します。\n
///   : 詳しくはeParentTypeを参照してください。
///
/// @retval true  : 属している。
/// @retval false : 属していない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::CheckBelongComponent
    ( _in<sdptr<Component>> in_sp_component_for_parent
    , _in<eParentType     > in_flag_parent
    ) noexcept
{
  auto sp_comp( GetLinkMyself() );

  while( sp_comp )
  {
    if( sp_comp == in_sp_component_for_parent )
    {
      return true;
    }

    sp_comp = sp_comp->GetBelongComponent( in_flag_parent );
  }

  return false;
}


// _____________________________________________________________________________
/// @brief コンポーネント位置の設定
/// 
/// @copydoc doxycomment::arg_in_position_for_component
/// 
/// @retval true  : 位置変更有り。
/// @retval false : 位置変更無し。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::SetPosition( _in<float2> in_position_for_component )
{
  if( m_rect.x == in_position_for_component.x
   && m_rect.y == in_position_for_component.y )
  {
    return false;
  }

  float2 size( m_rect.Width(), m_rect.Height() );
  m_rect.x = in_position_for_component.x;
  m_rect.y = in_position_for_component.y;
  m_rect.z = in_position_for_component.x + size.x;
  m_rect.w = in_position_for_component.y + size.y;

  call_On_Move( this->GetLinkMyself() );

  return true;
}


// _____________________________________________________________________________
/// @brief コンポーネント位置の移動
/// 
/// @copydoc doxycomment::arg_in_movevalue_for_component
/// 
/// @retval true  : 位置変更有り。
/// @retval false : 位置変更無し。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::MovePosition( _in<float2> in_movevalue_for_component )
{
  if( in_movevalue_for_component == float2{0,0} )
  {
    return false;
  }

  m_rect.x += in_movevalue_for_component.x;
  m_rect.y += in_movevalue_for_component.y;
  m_rect.z += in_movevalue_for_component.x;
  m_rect.w += in_movevalue_for_component.y;

  call_On_Move( this->GetLinkMyself() );

  return true;
}


// _____________________________________________________________________________
/// @brief コンポーネントサイズの設定
/// 
/// @copydoc doxycomment::arg_in_size_for_component
/// 
/// @retval true  : サイズ変更有り。
/// @retval false : サイズ変更無し。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::SetSize( _in<float2> in_size_for_component )
{
  auto size = in_size_for_component;
  if( size.x < 0 )
  {
    size.x = m_rect.Width();
  }
  if( size.y < 0 )
  {
    size.y = m_rect.Height();
  }

  if( Abs(m_rect.Width() - size.x) < 0.01f
   && Abs(m_rect.Height() - size.y) < 0.01f )
  {
    return false;
  }

  m_rect.z = m_rect.x + size.x;
  m_rect.w = m_rect.y + size.y;

  call_On_Size( this->GetLinkMyself() );

  return true;
}


// _____________________________________________________________________________
/// @brief コンポーネントの矩形座標の設定。
/// 
/// @param[in] in_rect
///   : 設定する座標を指定します。\n
///   : 値は親コンポーネントからの相対座標となります。
/// @param[in] in_flag_element
///   : WIN::Component::eRectFlag::Allを指定。\n
///   : 詳しくはeRectFlag::Allを参照してください。
/// 
/// @retval true  : 座標もしくはサイズ変更あり。
/// @retval false : 座標もしくはサイズに変更なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::SetRectCoord
    ( _in<float4                   > in_rect
    , _in<WIN::Component::eRectFlag> in_flag_element
    )
{
  float4 rt_old = m_rect;

  if( in_flag_element == WIN::Component::eRectFlag::All )
  {
    m_rect = in_rect;
  }
  else
  {
    if( in_flag_element & WIN::Component::eRectFlag::Left )
    {
      m_rect.x = in_rect.x;
    }
    if( in_flag_element & WIN::Component::eRectFlag::Top )
    {
      m_rect.y = in_rect.y;
    }
    if( in_flag_element & WIN::Component::eRectFlag::Right )
    {
      m_rect.z = in_rect.z;
    }
    if( in_flag_element & WIN::Component::eRectFlag::Bottom )
    {
      m_rect.w = in_rect.w;
    }
  }

  bool flag_difference = false;
  if( rt_old.x != m_rect.x  ||  rt_old.y != m_rect.y )
  {
    call_On_Move( this->GetLinkMyself() );
    flag_difference = true;
  }
  if( rt_old.Width() != m_rect.Width()  ||  rt_old.Height() != m_rect.Height() )
  {
    call_On_Size( this->GetLinkMyself() );
    flag_difference = true;
  }

  return flag_difference;
}


// _____________________________________________________________________________
/// @brief 最前面移動処理
/// 
/// アクティブ化などにおける、コンポーネントの最前面への移動処理。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::ActivateTopOrder()
{
  if( auto sp_comp_parent = GetLinkParent() )
  {
    sp_comp_parent->ActivateTopOrder();
  }
  if( typeid(*this) == typeid(Layer)
   || typeid(*this) == typeid(MasterLayer) )
  {
    return;
  }

  auto sp_comp = GetLinkNext();
  while( sp_comp )
  {
    if( typeid(*sp_comp) == typeid(Layer) )
    {
      break;
    }
    sp_comp = sp_comp->GetLinkNext();
  }

  if( sp_comp )
  {
    sp_comp->AddLinkPrev( GetLinkMyself() );
  }
  else
  {
    this->MoveLinkEnd();
  }
}


// _____________________________________________________________________________
/// @brief クローンの作成
/// 
/// @copydetails doxycomment::arg_in_sp_component_for_parent \n
///   : nullptrを指定すると、複製元の親が使用されます。\n
/// @copydetails doxycomment::arg_in_offset_position_from_original
/// 
/// @return 複製されたオブジェクトを指すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Component::CreateClone
    ( _in<sdptr<Component>> in_sp_component_for_parent
    , _in<float2          > in_offset_position_from_original
    ) const
{
  return
    zzz_CreateClone_Basic<td_self>
      ( in_sp_component_for_parent
      , in_offset_position_from_original
      );
}


// _____________________________________________________________________________
// リンクコピー
// in_sp_target : コピー先のオブジェクト
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::zzz_PasteCloneLink( _in<sdptr<Component>> in_sp_target ) const
{
  if( in_sp_target == nullptr )
  {
    return;
  }

  // 子供複製ループは、メニューコンポーネントのみを対象とするのではなく、
  // 全てのコンポーネントを対象とする事。
  // そのため、GetMenu_Child()ではなくGetLinkChild()を用いること。
  auto sp_child = GetLinkChild();
  while( sp_child )
  {
    sp_child->CreateClone( in_sp_target );
    sp_child = sp_child->GetLinkNext();
  }
}

// _____________________________________________________________________________
/// @brief 描画イベント
/// 
/// ※ デフォルトの動作では親へ通知しません。
/// 
/// @param[in] in_sp_draw_owner
///   : 描画オーナーのスマートポインタが渡されます。
/// @param[in] in_offset_position_from_parent
///   : 親からのオフセット座標が渡されます。\n
///   : これは、位置関係上の親とin_sp_draw_ownerが同じ場合のみ適応されます。
/// 
/// @return 自身の座標を反映させた新しいオフセットを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2
  Component::On_Paint
    ( _in<sdptr<Component>> in_sp_draw_owner
    , _in<float2          > in_offset_position_from_parent
    )
{
  const float fw = GetFrameSize();
  float4 rt = m_rect;
  auto sp_comp_parent_render = GetBelongComponent( eParentType::Render );
  auto sp_comp_parent_pos    = GetBelongComponent( eParentType::Position );
  if( sp_comp_parent_render == sp_comp_parent_pos )
  {
    rt.x += in_offset_position_from_parent.x;
    rt.y += in_offset_position_from_parent.y;
    rt.z += in_offset_position_from_parent.x;
    rt.w += in_offset_position_from_parent.y;
  }
  else
  {
    // オーナーウィンドウ座標への変換
    MappingPosition
      ( sp_comp_parent_pos
      , in_sp_draw_owner //IsOwner() ? nullptr : in_sp_draw_owner
      , (float2_ptr)&rt
      , 2
      );
  }

  if( m_flag_draw_bg )
  {
    On_DrawBackground( rt + float4(fw,fw, -fw+1,-fw+1) );
  }
  if( m_flag_draw_frame )
  {
    On_DrawFrame( rt );
  }
  if( m_flag_draw_client )
  {
    On_DrawClient( rt + float4(fw,fw, -fw,-fw)  );
  }

  if( GetLinkParent() == nullptr  &&  GetLinkNext() == nullptr )
  {
    //
    sm_def_font_mng()->Translate( sm_ptr_d3ddev() );
    sm_def_sprite_mng().Transrate();
  }

  return { rt.x, rt.y };
}


// _____________________________________________________________________________
/// @brief 背景描画イベント
/// 
/// @param[in] in_rect : コンポーネントの矩形座標が渡されます。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::On_DrawBackground( _in<float4> in_rect )
{
  auto ptr_color = &m_sp_color_bg->color_default;
  if( !this->IsEnable() )
  {
    ptr_color = &m_sp_color_bg->color_invalid;
  }
  else
  if( sm_sp_ac_comp() == this->GetLinkMyself() )
  {
    if( WIN::Mouse::GetDownL() )
    {
      ptr_color = &m_sp_color_bg->color_active;
    }
    else
    {
      ptr_color = &m_sp_color_bg->color_highlight;
    }
  }
  zzf_DrawRectEx( in_rect, ptr_color->color );
}


// _____________________________________________________________________________
/// @brief コンポーネント枠描画イベント
/// 
/// @param[in] in_rect : コンポーネントの矩形座標が渡されます。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::On_DrawFrame( _in<float4> in_rect )
{
  auto ptr_color = &m_sp_color_frame->color_default;
  if( !this->IsEnable() )
  {
    ptr_color = &m_sp_color_frame->color_invalid;
  }
  else
  if( sm_sp_ac_comp() == this->GetLinkMyself() )
  {
    if( WIN::Mouse::GetDownL() )
    {
      ptr_color = &m_sp_color_frame->color_active;
    }
    else
    {
      ptr_color = &m_sp_color_frame->color_highlight;
    }
  }
  zzf_DrawFrameEx( in_rect, ptr_color->color );
}


// _____________________________________________________________________________
/// @brief 親コンポーネントを取得
/// 
/// @param[in]  in_type_parent : 取得する親のタイプを指定します。
/// @param[out] out_comp_list  : 取得するコンポーネントを格納する配列を指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size_t
  Component::GetBelongComponent
    ( _in <eParentType                  > in_type_parent
    , rout<std::vector<sdptr<Component>>> out_comp_list
    ) const noexcept
{
  std::set<sdptr<Component>> comp_set;

  if( in_type_parent & eParentType::Position )
  {
    comp_set.insert( m_wp_comp_belong.lock() );
  }
  if( in_type_parent & eParentType::Render )
  {
    comp_set.insert( GetLinkParent() );
  }

  out_comp_list.clear();
  for( auto& sp_comp : comp_set )
  {
    out_comp_list.push_back( sp_comp );
  }

  return out_comp_list.size();
}


// _____________________________________________________________________________
/// @brief マスターレイヤーの取得
/// 
/// @return 属するマスターレイヤーのスマートポインタが返ります。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component> Component::GetMasterLayer() const
{
  auto sp_layer = GetLinkMyself();
  do
  {
    if( auto sp_layer_master = std::dynamic_pointer_cast<MasterLayer>(sp_layer) )
    {
      return sp_layer_master;
    }
    sp_layer = sp_layer->GetLinkParent();
  } while( sp_layer );

  return sp_layer;
}



// _____________________________________________________________________________
/// @brief IDからコンポーネントポインタを取得
/// 
/// @param[in] in_comp_ID : 検索するコンポーネントのIDを指定します。
/// 
/// @return
/// 検索されたコンポーネントのポインタが返します。\n
/// 指定されたIDに該当するコンポーネントが見つからない場合は、nullptrを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component* Component::ID_to_Pointer( _in<U32> in_comp_ID )
{
  if( sm_comp_table().size() <= in_comp_ID )
  {
    return nullptr;
  }
  else
  {
    return sm_comp_table()[ in_comp_ID ];
  }
}


// _____________________________________________________________________________
/// @brief ユーザーIDからコンポーネントポインタの検索
/// 
/// @param[in] in_user_ID : 検索するコンポーネントのユーザーIDを指定します。
/// 
/// @return
/// 検索されたコンポーネントのポインタを返します。\n
/// 該当するコンポーネントが見つからない場合は、nullptrを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Component::FindComponent_by_UserID( _in<std::string> in_user_ID ) const
{
  if( GetUserID() == in_user_ID )
  {
    return GetLinkMyself();
  }

  auto sp_component = GetLinkChild();
  while( sp_component )
  {
    auto hit = sp_component->FindComponent_by_UserID( in_user_ID );
    if( hit )
    {
      return hit;
    }

    sp_component = sp_component->GetLinkNext();
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 指定したコンポーネントのユーザーIDからコンポーネントポインタの検索
/// 
/// @param[in] in_sp_component
///   : 比較するコンポーネントのスマートポインタを指定します。
/// 
/// @return
/// 検索されたコンポーネントのスマートポインタを返します。\n
/// 該当するコンポーネントが見つからない場合は、nullptrを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Component::FindComponent_by_UserID( _in<sdptr<Component>> in_sp_component ) const
{
  if( in_sp_component )
  {
    return FindComponent_by_UserID( in_sp_component->GetUserID() );
  }
  return nullptr;
}



/// @cond
// _____________________________________________________________________________
// ポリゴン描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawPolygon
    ( pin<DrawVtxInfo              > in_ptr_vtx_table
    , _in<size_t                   > in_vtx_num
    , pin<U32                      > in_index_table
    , _in<U32                      > in_index_num
    , _in<DX::DX_PRIMITIVE_TOPOLOGY> in_prim_type
    , _in<DX::Matrix2D             > in_matrix
    )
{
  DX::DXDevice*  ptr_d3d_dev = sm_ptr_d3ddev();
  CPL_DBG_OUTPUT_RETURN_IF( !ptr_d3d_dev, SwS(CPL_DX_MSG_NOT_DEVICE) );

  // 頂点バッファの取得
  sdptr<DX::Buffer::DynamicEX_Vertex> sp_VB;
  sm_sp_RC_polygon()->GetFragment( sp_VB );
  const size_t vtx_num = sp_VB->GetElementNum();

  //
  if( vtx_num < in_vtx_num ) // バッファが作成されていない、もしくはバッファが不足している場合
  {
    // 頂点バッファ作成。
    sp_VB->Create
      ( sm_sp_layout_buf()->GetElementsSize(0)
      , in_vtx_num
      , nullptr
      );
  }

  UINT num = 1;
  DX::DX_VIEWPORT vp;
  DX::Graphics::GetImmediateContext()->RSGetViewports( &num, &vp );
  // スクリーン座標変換係数
  float c_scw =  2.0f / vp.Width;
  float c_sch = -2.0f / vp.Height;

  // 頂点設定
  //CPL_LOOP2( in_vtx_num, vtx_idx )
  for( size_t vtx_idx = 0; vtx_idx < in_vtx_num; ++vtx_idx )
  {
    DrawVtxInfo const& vi = in_ptr_vtx_table[ vtx_idx ];
    float2 tmp_xy{ vi.x - 0.5f, vi.y - 0.5f };
    Math::D2<>::VecTransform( tmp_xy, in_matrix );
    DX::Vtx::XYZWC
      vtx( tmp_xy.x * c_scw - 1.0f
         , tmp_xy.y * c_sch + 1.0f
         , vi.z
         , 1.0f
         , vi.color
         );
    sp_VB->SetData( vtx_idx, &vtx, 1 );
  }

  // インデックスバッファの取得。
  sdptr<DX::Buffer::DynamicEX_Index> sp_IB;
  sm_sp_RC_polygon()->GetFragment( sp_IB );
  const size_t idx_num = sp_IB->GetElementNum();
  //
  if( idx_num < in_index_num )
  {
    // インデックスバッファ作成。
    sp_IB->Create( sizeof(U32), in_index_num, nullptr );
  }
  // インデックス設定。
  sp_IB->SetData( 0, in_index_table, in_index_num );

  //
  auto& cp_d3d_DC = DX::Graphics_i_::GetImmediateContext();
  sm_sp_RC_polygon()->RenderSetup( cp_d3d_DC );

  // 背景エリアの描画
  cp_d3d_DC->IASetPrimitiveTopology( in_prim_type );
  //cp_d3d_DC->Draw( static_cast<UINT>(in_vtx_num), 0 );
  cp_d3d_DC->DrawIndexed( in_index_num, 0, 0 );
}
/// @endcond

/// @cond
// _____________________________________________________________________________
// ライン描画拡張版
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void 
  Component::zzf_DrawPolyLineEx
    ( pin<DrawVtxInfo2> in_ptr_vtx_table
    , _in<size_t      > in_vtx_num
    , _in<bool        > in_is_closed
    )
{
  DX::Matrix2D mtx;
  mtx.Identity();
  zzf_DrawPolyLineEx2( in_ptr_vtx_table, in_vtx_num, in_is_closed, mtx );
}

// _____________________________________________________________________________
// ライン描画拡張版
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void 
  Component::zzf_DrawPolyLineEx2
    ( pin<DrawVtxInfo2> in_ptr_vtx_table
    , _in<size_t      > in_vtx_num
    , _in<bool        > in_is_closed
    , _in<DX::Matrix2D> in_mtx
    )
{
  if( in_vtx_num < 2 )
  {
    return;
  }

  DX::DXDevice*  ptr_d3d_dev = sm_ptr_d3ddev();
  CPL_DBG_OUTPUT_RETURN_IF( !ptr_d3d_dev, SwS(CPL_DX_MSG_NOT_DEVICE) );

  // 頂点バッファの取得
  sdptr<DX::Buffer::DynamicEX_Vertex> sp_VB;
  sm_sp_RC_polygon()->GetFragment( sp_VB );
  const size_t vtx_num_new = in_vtx_num * 2 + in_is_closed * 2;
  const size_t vtx_num_old = sp_VB->GetElementNum();

  //
  if( vtx_num_old < vtx_num_new ) // バッファが作成されていない、もしくはバッファが不足している場合
  {
    // 頂点バッファ作成。
    sp_VB->Create
      ( sm_sp_layout_buf()->GetElementsSize(0)
      , vtx_num_new
      , nullptr
      );
  }

  UINT num = 1;
  DX::DX_VIEWPORT vp;
  DX::Graphics::GetImmediateContext()->RSGetViewports( &num, &vp );
  // スクリーン座標変換係数
  float c_scw = 2.0f / vp.Width;
  float c_sch = -2.0f / vp.Height;

  // 閉じない場合のダミーの頂点（法線計算用）
  DrawVtxInfo2 vtx_d0 =
  { in_ptr_vtx_table[ 0 ].x * 2 - in_ptr_vtx_table[ 1 ].x
  , in_ptr_vtx_table[ 0 ].y * 2 - in_ptr_vtx_table[ 1 ].y
  , in_ptr_vtx_table[ 0 ].z
  , in_ptr_vtx_table[ 0 ].w
  , in_ptr_vtx_table[ 0 ].color
  };
  DrawVtxInfo2 vtx_d1 =
  { in_ptr_vtx_table[ in_vtx_num-1 ].x * 2 - in_ptr_vtx_table[ in_vtx_num-2 ].x
  , in_ptr_vtx_table[ in_vtx_num-1 ].y * 2 - in_ptr_vtx_table[ in_vtx_num-2 ].y
  , in_ptr_vtx_table[ in_vtx_num-1 ].z
  , in_ptr_vtx_table[ in_vtx_num-1 ].w
  , in_ptr_vtx_table[ in_vtx_num-1 ].color
  };

  // 頂点設定
  int idx_vtx_base = 0;
  DX::Vector2 vec1, vec2, nor1, nor2, nor;
  auto const vtx_idx_end = in_vtx_num - 1;
  //CPL_LOOP2( in_vtx_num, vtx_idx ) // これは、入力テーブルの数のループ
  for( size_t vtx_idx = 0; vtx_idx < in_vtx_num; ++vtx_idx ) // これは、入力テーブルの数のループ
  {
    DrawVtxInfo2 const *p_v0, *p_v1, *p_v2;

    if( vtx_idx == 0 )
    {
      p_v0 = in_is_closed ? in_ptr_vtx_table + in_vtx_num - 1 : &vtx_d0;
      p_v1 = in_ptr_vtx_table;
      p_v2 = in_ptr_vtx_table + 1;
    }
    else
    if( vtx_idx == vtx_idx_end )
    {
      p_v0 = in_ptr_vtx_table + in_vtx_num - 2;
      p_v1 = in_ptr_vtx_table + in_vtx_num - 1;
      p_v2 = in_is_closed ? in_ptr_vtx_table : &vtx_d1;
    }
    else
    {
      p_v0 = in_ptr_vtx_table + vtx_idx - 1;
      p_v1 = in_ptr_vtx_table + vtx_idx;
      p_v2 = in_ptr_vtx_table + vtx_idx + 1;
    }
    //
    float2 xy[ 3 ] =
    { { p_v0->x, p_v0->y }
    , { p_v1->x, p_v1->y }
    , { p_v2->x, p_v2->y }
    };
    Math::D2<>::VecTransform( &xy[ 0 ].x, in_mtx );
    Math::D2<>::VecTransform( &xy[ 1 ].x, in_mtx );
    Math::D2<>::VecTransform( &xy[ 2 ].x, in_mtx );
    // 太さ適用のため２辺の法線を求め、共有頂点の法線ベクトルを求める。
    vec1 = DX::Vector2( xy[1].x - xy[0].x, xy[1].y - xy[0].y );
    vec2 = DX::Vector2( xy[2].x - xy[1].x, xy[2].y - xy[1].y );
    nor1 = DX::Vector2( -vec1.y,  vec1.x );
    nor2 = DX::Vector2( -vec2.y,  vec2.x );
    Math::D2<float>::VecNormalize( nor1 );
    Math::D2<float>::VecNormalize( nor2 );
    nor = { nor1.x + nor2.x, nor1.y + nor2.y };
    Math::D2<float>::VecNormalize( nor );
    float const width = p_v1->w * 0.5f;
    nor *= 0.5f * width;
    // 設定するデータを作成。
    DX::Vtx::XYZWC vtx[2] =
    {
      { (xy[1].x + nor.x - 0.5f) * c_scw - 1.0f
      , (xy[1].y + nor.y - 0.5f) * c_sch + 1.0f
      , p_v1->z
      , 1.0f
      , p_v1->color
      },
      { (xy[1].x - nor.x - 0.5f) * c_scw - 1.0f
      , (xy[1].y - nor.y - 0.5f) * c_sch + 1.0f
      , p_v1->z
      , 1.0f
      , p_v1->color
      },
    };
    // 頂点バッファにデータを設定。
    sp_VB->SetData( vtx_idx*2, &vtx, 2 );
  }
  if( in_is_closed )
  {
    DX::Vtx::XYZWC v[2];
    sp_VB->GetData( 0, v, 2 );
    sp_VB->SetData( in_vtx_num * 2, v, 2 );
  }

  // インデックスバッファの取得。
  sdptr<DX::Buffer::DynamicEX_Index> sp_IB;
  sm_sp_RC_polygon()->GetFragment( sp_IB );
  const size_t idx_num_old = sp_IB->GetElementNum();
  const size_t idx_num_new = vtx_num_new * 3 - 6;
  //
  if( idx_num_old < idx_num_new )
  {
    // インデックスバッファ作成。
    sp_IB->Create( sizeof(U32), idx_num_new, nullptr );
  }
  // インデックス設定。
  for( U32 idx_IB = 2; idx_IB < vtx_num_new; idx_IB += 2 )
  {
    U32 idx_data[] =
    { idx_IB-2, idx_IB, idx_IB-1
    , idx_IB-1, idx_IB, idx_IB+1
    };
    sp_IB->SetData( (idx_IB-2)*3, idx_data, 6 );
  }

  //
  auto& cp_d3d_DC = DX::Graphics_i_::GetImmediateContext();
  sm_sp_RC_polygon()->RenderSetup( cp_d3d_DC );

  // 背景エリアの描画
  cp_d3d_DC->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
  //cp_d3d_DC->Draw( static_cast<UINT>(in_vtx_num), 0 );
  cp_d3d_DC->DrawIndexed( static_cast<U32>(idx_num_new), 0, 0 );
}
/// @endcond


/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 矩形塗りつぶし描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawRect
    ( _in<float4       > in_rect
    , _in<DX::ColorType> in_color
    )
{
  DrawVtxInfo vtx_table[4] =
  { DrawVtxInfo( in_rect.x,      in_rect.y,      0.0f, in_color )
  , DrawVtxInfo( in_rect.z+1.0f, in_rect.y,      0.0f, in_color )
  , DrawVtxInfo( in_rect.x,      in_rect.w+1.0f, 0.0f, in_color )
  , DrawVtxInfo( in_rect.z+1.0f, in_rect.w+1.0f, 0.0f, in_color )
  };

  // インデックス。
  static U32 const index[] = { 0,1,2, 2,1,3 };

  zzf_DrawPolygon
    ( vtx_table
    , CPL_ARRAY_NUM(vtx_table)
    , index
    , CPL_ARRAY_NUM(index)
    , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    );
}
/// @endcond

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 矩形塗りつぶし描画（４点カラー）
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawRectEx
    ( _in<float4  > in_rect
    , DX::ColorType in_color_table[4]
    )
{
  auto color = in_color_table;
  // 重心座標。
  float center_x = (in_rect.left + in_rect.right) / 2.0f;
  float center_y = (in_rect.top + in_rect.bottom) / 2.0f;
  // 重心カラー。
  DX::ColorType center_color = (color[0] + color[1] + color[2] + color[3]) / 4.0f;
  // 頂点準備。
  DrawVtxInfo vtx_table[] =
  { DrawVtxInfo( center_x,       center_y,       0.0f, center_color )
  , DrawVtxInfo( in_rect.x,      in_rect.y,      0.0f, color[0] )
  , DrawVtxInfo( in_rect.z+1.0f, in_rect.y,      0.0f, color[1] )
  , DrawVtxInfo( in_rect.x,      in_rect.w+1.0f, 0.0f, color[2] )
  , DrawVtxInfo( in_rect.z+1.0f, in_rect.w+1.0f, 0.0f, color[3] )
  };
  // インデックス。
  static U32 const index[] = {
    0, 1, 2,
    0, 2, 4,
    0, 4, 3,
    0, 3, 1,
  };

  zzf_DrawPolygon
    ( vtx_table
    , CPL_ARRAY_NUM(vtx_table)
    , index
    , CPL_ARRAY_NUM(index)
    , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    );
}
/// @endcond

//// _____________________________________________________________________________
//// デフォルトの背景描画
//// _____________________________________________________________________________
//void
//  Component::zzf_DrawRect_DefaultComponentBG(
//    short4               in_rect,
//    DX::ColorType const& in_color )
//{
//  ++in_rect.x;
//  ++in_rect.y;
//  --in_rect.z;
//  --in_rect.w;
//
//  const float r = in_color.r;
//  const float g = in_color.g;
//  const float b = in_color.b;
//  const float a = in_color.a;
//  const float k0 = 0.9f;
//  const float k1 = 0.8f;
//  const float k2 = 0.7f;
//  DX::ColorType color[] = {
//    DX::ColorType( r,    g,    b,    a ),
//    DX::ColorType( r*k0, g*k0, b*k0, a ),
//    DX::ColorType( r*k1, g*k1, b*k1, a ),
//    DX::ColorType( r*k2, g*k2, b*k2, a ),
//  };
//
//  zzf_DrawRectEx( in_rect, color );
//}

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 枠描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawFrame
    ( _in<float4       > in_rect
    , _in<DX::ColorType> in_color
    )
{
  auto        rect       = in_rect;
  float const size_frame = static_cast<float>(GetFrameSize()); // frame width
  //
  ++rect.x;
  ++rect.y;
  float x0 = rect.x;
  float x2 = rect.x + size_frame;
  float x3 = rect.z + 1.0f - size_frame;
  float x5 = rect.z + 1.0f;
  float y0 = rect.y;
  float y2 = rect.y + size_frame;
  float y3 = rect.w + 1.0f - size_frame;
  float y5 = rect.w + 1.0f;
  DrawVtxInfo vtx_table[] =
  { DrawVtxInfo( x2,   y2,   0.0f, in_color )
  , DrawVtxInfo( x0,   y0,   0.0f, in_color )
  , DrawVtxInfo( x2,   y0,   0.0f, in_color )
  , DrawVtxInfo( x3,   y0,   0.0f, in_color )
  , DrawVtxInfo( x5,   y0,   0.0f, in_color )
  , DrawVtxInfo( x3,   y2,   0.0f, in_color )

  , DrawVtxInfo( x3,   y2,   0.0f, in_color )
  , DrawVtxInfo( x5,   y0,   0.0f, in_color )
  , DrawVtxInfo( x5,   y2+1, 0.0f, in_color )
  , DrawVtxInfo( x5,   y3-2, 0.0f, in_color )
  , DrawVtxInfo( x5-1, y5-1, 0.0f, in_color )
  , DrawVtxInfo( x3,   y3,   0.0f, in_color )

  , DrawVtxInfo( x3,   y3,   0.0f, in_color )
  , DrawVtxInfo( x5-1, y5-1, 0.0f, in_color )
  , DrawVtxInfo( x3-2, y5,   0.0f, in_color )
  , DrawVtxInfo( x2+1, y5,   0.0f, in_color )
  , DrawVtxInfo( x0,   y5-1, 0.0f, in_color )
  , DrawVtxInfo( x2,   y3,   0.0f, in_color )

  , DrawVtxInfo( x2,   y3,   0.0f, in_color )
  , DrawVtxInfo( x0,   y5-1, 0.0f, in_color )
  , DrawVtxInfo( x0,   y3-1, 0.0f, in_color )
  , DrawVtxInfo( x0,   y2,   0.0f, in_color )
  , DrawVtxInfo( x0,   y0,   0.0f, in_color )
  , DrawVtxInfo( x2,   y2,   0.0f, in_color )
  };

  // インデックス。
  static U32 const index[] =
  { 0,1,2, 0,2,5, 2,3,5, 3,4,5
  , 6,7,8, 6,8,11, 8,9,11, 9,10,11
  , 12,13,14, 12,14,17, 14,15,17, 15,16,17
  , 18,19,20, 18,20,23, 20,21,23, 21,22,23
  };
  
  zzf_DrawPolygon
    ( vtx_table
    , CPL_ARRAY_NUM(vtx_table)
    , index
    , CPL_ARRAY_NUM(index)
    //, D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP
    , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    );
}
/// @endcond

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 枠描画　※ 各辺色指定バージョン
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawFrameEx
    ( _in<float4  > in_rect
    , DX::ColorType in_color_table[4]
    )
{
  auto        rect       = in_rect;
  float const size_frame = static_cast<float>(GetFrameSize()); // frame width
  //
  ++rect.x;
  ++rect.y;
  auto& c0 = in_color_table[0];
  auto& c1 = in_color_table[1];
  auto& c2 = in_color_table[2];
  auto& c3 = in_color_table[3];
  float x0 = rect.x;
  float x2 = rect.x + size_frame;
  float x3 = rect.z + 1.0f - size_frame;
  float x5 = rect.z + 1.0f;
  float y0 = rect.y;
  float y2 = rect.y + size_frame;
  float y3 = rect.w + 1.0f - size_frame;
  float y5 = rect.w + 1.0f;
  DrawVtxInfo vtx_table[] =
  { DrawVtxInfo( x2,   y2,   0.0f, c0 )
  , DrawVtxInfo( x0,   y0,   0.0f, (c0+c3)/2.0f )
  , DrawVtxInfo( x2,   y0,   0.0f, c0 )
  , DrawVtxInfo( x3,   y0,   0.0f, c0 )
  , DrawVtxInfo( x5,   y0,   0.0f, (c0+c1)/2.0f )
  , DrawVtxInfo( x3,   y2,   0.0f, c0 )

  , DrawVtxInfo( x3,   y2,   0.0f, c1 )
  , DrawVtxInfo( x5,   y0,   0.0f, (c0+c1)/2.0f )
  , DrawVtxInfo( x5,   y2+1, 0.0f, c1 )
  , DrawVtxInfo( x5,   y3-2, 0.0f, c1 )
  , DrawVtxInfo( x5-1, y5-1, 0.0f, (c1+c2)/2.0f )
  , DrawVtxInfo( x3,   y3,   0.0f, c1 )

  , DrawVtxInfo( x3,   y3,   0.0f, c2 )
  , DrawVtxInfo( x5-1, y5-1, 0.0f, (c1+c2)/2.0f )
  , DrawVtxInfo( x3-2, y5,   0.0f, c2 )
  , DrawVtxInfo( x2+1, y5,   0.0f, c2 )
  , DrawVtxInfo( x0,   y5-1, 0.0f, (c2+c3)/2.0f )
  , DrawVtxInfo( x2,   y3,   0.0f, c2 )

  , DrawVtxInfo( x2,   y3,   0.0f, c3 )
  , DrawVtxInfo( x0,   y5-1, 0.0f, (c2+c3)/2.0f )
  , DrawVtxInfo( x0,   y3-1, 0.0f, c3 )
  , DrawVtxInfo( x0,   y2,   0.0f, c3 )
  , DrawVtxInfo( x0,   y0,   0.0f, (c3+c0)/2.0f )
  , DrawVtxInfo( x2,   y2,   0.0f, c3 )
  };

  // インデックス。
  static U32 const index[] =
  { 0,1,2, 0,2,5, 2,3,5, 3,4,5
  , 6,7,8, 6,8,11, 8,9,11, 9,10,11
  , 12,13,14, 12,14,17, 14,15,17, 15,16,17
  , 18,19,20, 18,20,23, 20,21,23, 21,22,23
  };

  zzf_DrawPolygon
    ( vtx_table
    , CPL_ARRAY_NUM(vtx_table)
    , index
    , CPL_ARRAY_NUM(index)
    , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    );

}
/// @endcond

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// コンポーネント用テキスト描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawText
    ( _in<float4         > in_rect
    , pin<td_DefChar     > in_text
    , _in<DX::RectColor4P> in_color
    , _in<float          > in_rotate_z
    , _in<float2         > in_rotate_center
    , _in<DWORD          > in_flags_draw_style
    )
{
  auto sp_font_mng = sm_def_font_mng();
  CPL_DBG_OUTPUT_RETURN_IF( !sp_font_mng, SwS(CPL_DX_MSG_NOT_DEFAULT_FONT) );

  // 文字描画。
//#ifdef CPL_UNICODE
  DX::FontDrawManager::MsgInfo
    mi( in_text
      , WIN::Rect( (long)in_rect.x, (long)in_rect.y, (long)in_rect.z, (long)in_rect.w )
      , 0.0f
      , U32x4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
      , in_rotate_z
      , in_rotate_center
      );
//#else
//  Core::StringW wstr;
//  Core::ChangeCodeStrings( wstr, in_text );
//  DX::FontDrawManager::MsgInfo
//    mi( wstr
//      , &WIN::Rect( in_rect.x, in_rect.y, in_rect.z, in_rect.w )
//      , 0.0f
//      , U32x4(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff)
//      , in_rotate_z
//      , in_rotate_center
//      );
//#endif

  mi.flags = in_flags_draw_style;

  // 文字背景色設定。
  DX::RectColor4P rev_color_bg;
  CPL_LOOP2( 4, idx )
  {
    rev_color_bg.color[idx].r = in_color.color[idx].r > 0.5f ? 0.0f : 1.0f;
    rev_color_bg.color[idx].g = in_color.color[idx].g > 0.5f ? 0.0f : 1.0f;
    rev_color_bg.color[idx].b = in_color.color[idx].b > 0.5f ? 0.0f : 1.0f;
    //rev_color_bg.color[idx].r = 1.0f;
    //rev_color_bg.color[idx].g = 1.0f;
    //rev_color_bg.color[idx].b = 1.0f;
    rev_color_bg.color[idx].a = 1.0f;

  }

  mi.rect.left   += 1;
  mi.rect.top    += 1;
  mi.rect.right  += 1;
  mi.rect.bottom += 1;
  rev_color_bg.ConvertColor_to_U32x4( mi.default_color );
  sp_font_mng->DrawMessage( mi );

  mi.rect.left   -= 1;
  mi.rect.top    -= 1;
  mi.rect.right  -= 1;
  mi.rect.bottom -= 1;
  in_color.ConvertColor_to_U32x4( mi.default_color );

  sp_font_mng->DrawMessage( mi );
  sp_font_mng->Translate( sm_ptr_d3ddev() );
}
/// @endcond

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 基本パーツの描画
// 一つのパーツは16*16固定サイズ。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawParts
    ( _in<float2       > in_pos
    , _in<eImagePartsID> in_parts_ID
    , _in<DX::ColorType> in_color
    , _in<float2       > in_scale
    )
{
  auto color = in_color;

  color.a = static_cast<float>(color.a * sm_all_applied_draw_alpha());
  Clamp( color.a, 0.0f, 1.0f );

  sm_def_sprite_mng().Draw
    ( sm_tex_parts()
    , in_pos
    , float4( 0, static_cast<float>(in_parts_ID*16),
              16, static_cast<float>(in_parts_ID*16+16) )
    , 0.0f
    , color
    , float2(0,0)
    , in_scale
    );

  sm_def_sprite_mng().Transrate();
}
/// @endcond

/// @cond
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 円の描画
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_DrawCircle
    ( _in<float2       > in_pos
    , _in<float        > in_R
    , _in<DX::ColorType> in_color
    , _in<bool         > in_flag_fill
    )
{
  CPL_DBG_OUTPUT_RETURN_IF
    ( !DX::Graphics_i_::GetImmediateContext()
    , SwS("Failed to Immediate Context.\n")
    );

  static constexpr int corner_n = 16;
  static DrawVtxInfo vtx_circle[ corner_n + 1 ];

  for( int i = 0; i < corner_n; ++i )
  {
    DrawVtxInfo& v = vtx_circle[ i ];
    v.x = Math::Cos(360 * i / corner_n) * in_R + in_pos.x;
    v.y = Math::Sin(360 * i / corner_n) * in_R + in_pos.y;
    v.z = 0.0f;
    v.color = in_color;
  }
  
  //vtx_circle[ corner_n ] = vtx_circle[ 0 ];

  if( in_flag_fill ) // 塗りつぶし付の円。
  {
    auto& vc = vtx_circle[ corner_n ];
    vc.x = in_pos.x;
    vc.y = in_pos.y;
    vc.z = 0.0f;
    vc.color = in_color;
    // インデックス。
    static U32 const* index = [&]() -> U32 const*
    {
      static U32 index_[ corner_n * 3 ];
      for( int i = 0; i < corner_n; ++i )
      {
        index_[ i * 3 ] = corner_n;
        index_[ i * 3 + 1 ] = i % corner_n;
        index_[ i * 3 + 2 ] = (i+1) % corner_n;
      }
      return index_;
    }();

    // 描画
    zzf_DrawPolygon
      ( vtx_circle
      , CPL_ARRAY_NUM(vtx_circle)
      , index
      , corner_n * 3
      , D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
      );
  }
  else // 円のラインのみ。
  {
    // インデックス。
    static U32 const index[ corner_n + 1 ] = {
      0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,0,
    };

    // 描画
    zzf_DrawPolygon
      ( vtx_circle
      , CPL_ARRAY_NUM(vtx_circle)
      , index
      , CPL_ARRAY_NUM(index)
      , D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP
      );
  }
}
/// @endcond


/// @cond
// _____________________________________________________________________________
/// @brief 描画ステートの初期設定。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  Component::zzf_setupDrawState
    ( _in<bool> in_flag_draw_bg
    , _in<bool> in_flag_draw_frame
    , _in<bool> in_flag_draw_client
    )
{
  m_flag_draw_bg     = in_flag_draw_bg;
  m_flag_draw_frame  = in_flag_draw_frame;
  m_flag_draw_client = in_flag_draw_client;
}
/// @endcond


// _____________________________________________________________________________
/// @brief フォーカスの設定。
/// 
/// @param[in] in_sp_component : フォーカス対象とするコンポーネントを指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::SetFocus( _in<sdptr<Component>> in_sp_component )
{
  auto* is_type_edit = dynamic_cast<EditBase*>(&*sm_sp_focus());
  if( is_type_edit )
  {
    sm_sp_focus()->KillTimer( eID::Tid_CaretSwitch );
    sm_sp_focus()->Update();
  }

  sm_sp_focus( in_sp_component );

  is_type_edit = dynamic_cast<EditBase*>(&*sm_sp_focus());
  if( is_type_edit )
  {
    sm_sp_focus()->SetTimer( eID::Tid_CaretSwitch, 500 );
    sm_sp_focus()->Update();
  }
}


// _____________________________________________________________________________
// 汎用イベントコール
// 戻り値：false-親がいない状態で親をコール / true-正常終了
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Func, class... T_Params>
bool
  call_On_EventX_
    ( Component*    ptr_comp
    , bool          is_view
    , T_Func        func
    , T_Params&&... args
    )
{
  if( is_view  &&  !ptr_comp->IsEnable() )
  {
    return true;
  }

  auto ret = func( ptr_comp, std::forward<T_Params>(args)... );
  if( ret != eEventReturnID::LastCall )
  {
    auto sp_comp_belong_pos  =
      (ret & eEventReturnID::SendParent_Position)
        ? ptr_comp->GetBelongComponent( eParentType::Position )
        : nullptr;
    auto sp_comp_belong_rend =
      (ret & eEventReturnID::SendParent_Render)
        ? ptr_comp->GetBelongComponent( eParentType::Render )
        : nullptr;

    if( sp_comp_belong_pos  &&  sp_comp_belong_pos != sp_comp_belong_rend )
    {
      call_On_EventX_
        ( &*sp_comp_belong_pos
        , is_view
        , func
        , args...
        );
    }
    if( sp_comp_belong_rend )
    {
      return
        call_On_EventX_
          ( &*sp_comp_belong_rend
          , is_view
          , func
          , args...
          );
    }
  }
  return true;
}


// _____________________________________________________________________________
// 汎用イベントコール（マウス用）
// 戻り値：false-親がいない状態で親をコール / true-正常終了
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
template<class T_Func, class... T_Params>
bool
  call_On_EventX_forMouse_
    ( Component*  ptr_comp
    , T_Func      func
    , _in<sdptr<Component>> in_sp_component
    , float mx
    , float my
    , T_Params&&... args
    )
{
  if( !ptr_comp->IsEnable() )
  {
    return true;
  }

  auto ret = func( ptr_comp, in_sp_component, mx, my, std::forward<T_Params>(args)... );
  if( ret != eEventReturnID::LastCall )
  {
    auto sp_comp_belong_pos  =
      (ret & eEventReturnID::SendParent_Position)
        ? ptr_comp->GetBelongComponent( eParentType::Position )
        : nullptr;
    auto sp_comp_belong_rend =
      (ret & eEventReturnID::SendParent_Render)
        ? ptr_comp->GetBelongComponent( eParentType::Render )
        : nullptr;
    float2 pos = ptr_comp->GetPosition();

    if( sp_comp_belong_pos  &&  sp_comp_belong_pos != sp_comp_belong_rend )
    {
      call_On_EventX_forMouse_
        ( &*sp_comp_belong_pos
        , func, in_sp_component
        , mx + pos.x
        , my + pos.y
        , args...
        );
    }
    if( sp_comp_belong_rend )
    {
      return
        call_On_EventX_forMouse_
          ( &*sp_comp_belong_rend
          , func, in_sp_component
          , mx + pos.x
          , my + pos.y
          , args...
          );
    }
    return false;
  }
  return true;
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_MouseDown()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseDown
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    , _in<eMouseButton    > in_type_mouse_btn
    )
{
  return
    call_On_EventX_forMouse_
      ( this
      , std::mem_fn(&Component::On_MouseDown)
      , in_sp_component
      , in_mouse_x
      , in_mouse_y
      , in_type_mouse_btn
      );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_MouseUp()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseUp
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    , _in<eMouseButton    > in_type_mouse_btn
    )
{
  return
    call_On_EventX_forMouse_
      ( this
      , std::mem_fn(&Component::On_MouseUp)
      , in_sp_component
      , in_mouse_x
      , in_mouse_y
      , in_type_mouse_btn
      );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_MouseMove()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseMove
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    )
{
  return
    call_On_EventX_forMouse_
      ( this
      , std::mem_fn(&Component::On_MouseMove)
      , in_sp_component
      , in_mouse_x
      , in_mouse_y
      );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_MouseWheel()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseWheel
    ( _in<sdptr<Component>> in_sp_component
    , _in<WORD            > in_fw_keys
    , _in<short           > in_z_delta
    )
{
  return
    call_On_EventX_
      ( this
      , true
      , std::mem_fn(&Component::On_MouseWheel)
      , in_sp_component
      , in_fw_keys
      , in_z_delta
      );
}


// _____________________________________________________________________________
/// @brief On_MouseEnter()呼び出し関数
/// 
/// @param[in] in_sp_comp_enter
///   : 次に侵入したコンポーネントのスマートポインタが渡されます。
/// @param[in] in_sp_comp_leave
///   : 前に離脱したコンポーネントのスマートポインタが渡されます。
/// 
/// @return call_On_EventX_参照
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseEnter
    ( _in<sdptr<Component>> in_sp_comp_enter
    , _in<sdptr<Component>> in_sp_comp_leave
    )
{
  return
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_MouseEnter)
      , in_sp_comp_enter
      , in_sp_comp_leave
      );
}


// _____________________________________________________________________________
/// @brief On_MouseLeave()呼び出し関数
/// 
/// @param[in] in_sp_comp_leave
///   : 前に離脱したコンポーネントのスマートポインタが渡されます。
/// @param[in] in_sp_comp_enter
///   : 次に侵入したコンポーネントのスマートポインタが渡されます。
/// 
/// @return call_On_EventX_参照
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_MouseLeave
    ( _in<sdptr<Component>> in_sp_comp_leave
    , _in<sdptr<Component>> in_sp_comp_enter
    )
{
  return
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_MouseLeave)
      , in_sp_comp_leave
      , in_sp_comp_enter
      );
}

//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//// On_DblClick()の呼び出し
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void
//  Component::call_On_DblClick
//  ( _in<sdptr<Component>> in_sp_component,
//    int        in_mouse_x,
//    int        in_mouse_y )
//{
//  //
//  if( On_DblClick( in_sp_component, in_mouse_x, in_mouse_y ) == eEventReturnID::SendParent )
//  {
//    if( GetBelongComponent() )
//    {
//      in_mouse_x += this->m_rect.x;
//      in_mouse_y += this->m_rect.y;
//
//      GetBelongComponent()->
//        call_On_DblClick( in_sp_component, in_mouse_x, in_mouse_y );
//    }
//  }
//}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_KeyDown()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_KeyDown
    ( _in<sdptr<Component>> in_sp_component
    , _in<int             > in_virtual_key_code
    )
{
  return
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_KeyDown)
      , in_sp_component
      , in_virtual_key_code
      );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_KeyUp()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_KeyUp
    ( _in<sdptr<Component>> in_sp_component
    , _in<int             > in_virtual_key_code
    )
{
  return
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_KeyUp)
      , in_sp_component
      , in_virtual_key_code
      );
}



// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_Show()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_Show
    ( _in<sdptr<Component>> in_sp_component
    , _in<BOOL            > in_show_flag
    )
{
  auto res =
    call_On_EventX_
      ( this, false
      , std::mem_fn(&Component::On_Show)
      , in_sp_component
      , in_show_flag
      );
  // 子供等も呼び出す（戻り値は無視される）
  auto sp_child = in_sp_component->GetLinkChild();
  while( sp_child )
  {
    sp_child->call_On_Show( sp_child, in_show_flag );
    sp_child = sp_child->GetLinkNext();
  }

  return res;
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_Size()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::call_On_Size( _in<sdptr<Component>> in_sp_component )
{
  return
    call_On_EventX_
      ( this, false
      , std::mem_fn(&Component::On_Size)
      , in_sp_component
      );
}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_Move()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool Component::call_On_Move( _in<sdptr<Component>> in_sp_component )
{
  return
    call_On_EventX_
      ( this, false
      , std::mem_fn(&Component::On_Move)
      , in_sp_component
      );
}


//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//// On_Timer()の呼び出し
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//bool Component::call_On_Timer( _in<int> in_timer_ID )
//{
//  return
//    call_On_EventX_
//      ( this, false
//      , std::mem_fn(&Component::On_Timer)
//      , in_timer_ID
//      );
//}


// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_Char()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_Char
    ( _in<sdptr<Component>> in_sp_component
    , _in<TCHAR           > in_char_code
    , _in<int             > in_key_data
    )
{
  return
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_Char)
      , in_sp_component
      , in_char_code
      , in_key_data
      );
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// On_UserProc()の呼び出し
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
bool
  Component::call_On_UserProc
    ( _in<sdptr<Component>> in_sp_component
    , _in<long            > in_message
    , _in<WPARAM          > in_wparam
    , _in<LPARAM          > in_lparam
    )
{
  auto res =
    call_On_EventX_
      ( this, true
      , std::mem_fn(&Component::On_UserProc)
      , in_sp_component
      , in_message
      , in_wparam
      , in_lparam
      );

  if( res == false )
  {
    SendFrameMessage( in_message, in_wparam, in_lparam );
    return false;
  }
  return true;
}




// _____________________________________________________________________________
/// @brief タグ形式でコンポーネントのパラメタを取得
/// 
/// @param[out] out_tag
///   : 取得用のタグオブジェクトを渡します。
/// @param[in] in_types
///   : タグに設定したいデータのフラグの組み合わせを指定します。\n
///   : 詳しくはeTagTypesを参照してください。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::MakeTag( rout<TBTag> out_tag, _in<U64> in_types )
{
  using Tag = TBTag;

  if( in_types & WIN::eTagTypes::UserID )
  {
    out_tag.AddTag( Tag{ "UserID", this->GetUserID() } );
  }
  if( in_types & WIN::eTagTypes::Rect )
  {
    auto rt = this->GetRectCoord();
    out_tag.AddTag( Tag{ "Rect", rt.x, rt.y, rt.z, rt.w } );
  }
  if( in_types & WIN::eTagTypes::FrameWidth )
  {
    out_tag.AddTag( Tag{ "FrameWidth", this->GetFrameSize() } );
  }
  if( in_types & WIN::eTagTypes::IsVisible )
  {
    out_tag.AddTag( Tag{ "IsVisible", this->IsVisible() } );
  }
  if( in_types & WIN::eTagTypes::IsEnable )
  {
    out_tag.AddTag( Tag{ "IsEnable", this->IsEnable() } );
  }
  if( in_types & WIN::eTagTypes::ColorBG )
  {
    out_tag.AddTag( (ToTag( *this->GetColorParameterBG() ), "ColorBG") );
  }
  if( in_types & WIN::eTagTypes::ColorText )
  {
    out_tag.AddTag( (ToTag( *this->GetColorParameterText() ), "ColorText") );
  }
  if( in_types & WIN::eTagTypes::ColorFrame )
  {
    out_tag.AddTag( (ToTag( *this->GetColorParameterFrame() ), "ColorFrame") );
  }
}

// _____________________________________________________________________________
/// @brief タグ情報を元に設定
/// 
/// @param[in] in_tag
///   : 読み込み元のデータを保持するタグが渡されます。
/// @param[in] in_types
///   : タグに設定したいデータのフラグの組み合わせを指定します。\n
///   : 詳しくはeTagTypesを参照してください。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Component::LoadTag( _in<TBTag> in_tag, _in<U64> in_types )
{
  for // 子供タグループ
    ( auto sp_tag_item = in_tag.GetTagChild()
    ; sp_tag_item
    ; sp_tag_item = sp_tag_item->GetTagNext()
    )
  {
    auto sp_tag_data = sp_tag_item->GetTagChild();
    auto& name = sp_tag_item->GetName();

    if( in_types & WIN::eTagTypes::UserID  &&  name == "UserID" )
    {
      m_user_ID << *sp_tag_item;
    }
    else
    if( in_types & WIN::eTagTypes::Rect  &&  name == "Rect" )
    {
      m_rect << *sp_tag_item;
      On_Size( GetLinkMyself() );
    }
    else
    if( in_types & WIN::eTagTypes::FrameWidth  &&  name == "FrameWidth" )
    {
      m_frame_width << *sp_tag_item;
    }
    else
    if( in_types & WIN::eTagTypes::IsVisible  &&  name == "IsVisible" )
    {
      this->SetStateVisible( sp_tag_data->GetName() == "true" );
    }
    else
    if( in_types & WIN::eTagTypes::IsEnable  &&  name == "IsEnable" )
    {
      this->SetStateEnable( sp_tag_data->GetName() == "true" );
    }
    else
    if( in_types & WIN::eTagTypes::ColorBG  &&  name == "ColorBG" )
    {
      if( m_sp_color_bg )
        *m_sp_color_bg << *sp_tag_item;
    }
    else
    if( in_types & WIN::eTagTypes::ColorText  &&  name == "ColorText" )
    {
      if( m_sp_color_text )
        *m_sp_color_text << *sp_tag_item;
    }
    else
    if( in_types & WIN::eTagTypes::ColorFrame  &&  name == "ColorFrame" )
    {
      if( m_sp_color_frame )
        *m_sp_color_frame << *sp_tag_item;
    }
    else
    {
      On_LoadTagItem( *sp_tag_item );
    }
  }
}



} // namespace GUC
} // namespace CPL