/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2017/02/01
/// 
/// @brief  ボタン関連。
/// 
/// ****************************************************************************

#ifdef _MSC_VER
  #pragma comment(lib, "msimg32.lib")
#endif


#include "CPL_GUC_Button.h"


namespace CPL {
namespace GUC {

  
// _____________________________________________________________________________
/// @brief ボタンのデフォルト背景カラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Button::GetDefaultColor_ButtonBG()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicBG()
        );
  return sp_color;
}

// _____________________________________________________________________________
/// @brief ボタンのデフォルトフレームカラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Button::GetDefaultColor_ButtonFrame()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicFrame()
        );
  return sp_color;
}

// _____________________________________________________________________________
/// @brief ボタンのデフォルトテキストカラー。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet> Button::GetDefaultColor_ButtonText()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicText()
        );
  return sp_color;
}


// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @copydoc CPL::GUC::doxycomment::arg_in_sp_component_for_parent
/// @copydoc CPL::GUC::doxycomment::arg_in_position_for_component
/// @copydoc CPL::GUC::doxycomment::arg_in_size_for_component
/// @copydoc CPL::GUC::doxycomment::arg_in_string_for_button
/// @copydoc CPL::GUC::doxycomment::arg_in_string_for_tooltip
/// @param[in] in_button_type
///   : ボタンのタイプを指定します。\n
///   : 詳しくはeBtnTypeを参照してください。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Button::Button
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<float2          > in_position_for_component
, _in<float2          > in_size_for_component
, pin<td_DefChar      > in_string_for_button
, pin<td_DefChar      > in_string_for_tooltip
, _in<eBtnType        > in_button_type
) : td_base
    ( in_sp_component_for_parent
    , in_position_for_component
    , in_size_for_component
    )
{
  zzz_setFrameSize_( 1 );

  m_text     = in_string_for_button  ? in_string_for_button : CPL_GUC_DEF_STR("");
  m_message  = in_string_for_tooltip ? in_string_for_tooltip : CPL_GUC_DEF_STR("");
  m_btn_type = in_button_type;
  
  zzf_setupDrawState
    ( m_btn_type == eBtnType::Normal
    , m_btn_type == eBtnType::Normal
    , true
    ); // 描画ステートのデフォルト設定。
  zzf_SetInitializedLevel( zzf_GetClassLevel() );

  //
  if( in_size_for_component.x <= 0  ||  in_size_for_component.y <= 0 )
  {
    auto size = GetAdjustSize(false) + float2(2,2);

    if( in_size_for_component.x > 0 )
    {
      size.x = in_size_for_component.x;
    }
    if( in_size_for_component.y > 0 )
    {
      size.y = in_size_for_component.y;
    }

    //AdjustSize( float2(2,2) );
    SetSize( size );
  }
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Button::Button( cref<Button> in_button )
  : td_base( in_button )
  , m_btn_state( in_button.m_btn_state )
  , m_btn_type ( in_button.m_btn_type  )
  , m_message  ( in_button.m_message   )
  , m_text     ( in_button.m_text      )
{
}


// _____________________________________________________________________________
/// @brief デストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Button::~Button()
{
}


// _____________________________________________________________________________
/// @brief 補正済みサイズの取得
/// 
/// @param[in] in_flag_show : 使用しません。
/// 
/// @return 設定された文字列で補正されたサイズを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2 Button::GetAdjustSize( _in<BOOL> in_flag_show ) const noexcept
{
  // テキストのサイズを取得
//#ifdef CPL_UNICODE
  auto size =
    sm_def_font_mng()->GetStringLineSize( m_text, 0, nullptr );
//#else
//  auto size =
//    sm_def_font_mng()->GetStringLineSize
//      ( Core::ChangeCodeStrings( Core::StringW(), m_text ), 0, nullptr );
//#endif

  if( this->m_btn_type == eBtnType::Check
   || this->m_btn_type == eBtnType::AutoCheck
   || this->m_btn_type == eBtnType::Radio
   || this->m_btn_type == eBtnType::AutoRadio
    )
  {
    auto size_ckbox = zzf_getCheckBoxSize_();
    size.x += static_cast<short>(size_ckbox.right) + 2;
  }

  //
  return size + float2(6,2);
}



// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  Button::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
      );
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawBackground
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Button::On_DrawBackground( _in<float4> in_rect )
{
  td_base::On_DrawBackground( in_rect );
}



// _____________________________________________________________________________
// チェックボックスのサイズを計算
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float4 Button::zzf_getCheckBoxSize_() const
{
  auto  rect   = GetRectCoord();
  float scale  = rect.Height();
  float space  = scale * 0.2f;
  float size_y = scale * 0.8f;
  float4
    rt_check
    { space
    , space
    , scale-space
    , scale-space
    };
  return rt_check;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawClient
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void Button::On_DrawClient( _in<float4> in_rect )
{
  // color
  auto sp_colorset_text = GetColorParameterText();
  auto ptr_color = &sp_colorset_text->color_default;
  bool const is_auto_state = (m_btn_state.view_state == (int)eBtnViewState::Auto);

  if( is_auto_state )
  {
    bool const is_enable = IsEnable();
    bool const is_mouse_over = sm_sp_ac_comp() == this->GetLinkMyself();
    if( !is_enable )
    {
      ptr_color = &sp_colorset_text->color_invalid;
    }
    else
    if( is_mouse_over )
    {
      if( WIN::Mouse::GetDownL() ) // active
      {
        ptr_color = &sp_colorset_text->color_active;
      }
      else // highlight
      {
        ptr_color = &sp_colorset_text->color_highlight;
      }
    }
  }
  else
  {
    switch( (eBtnViewState)m_btn_state.view_state )
    {
    case eBtnViewState::Default:   ptr_color = &sp_colorset_text->color_default;   break;
    case eBtnViewState::HighLight: ptr_color = &sp_colorset_text->color_highlight; break;
    case eBtnViewState::Active:    ptr_color = &sp_colorset_text->color_active;    break;
    case eBtnViewState::Invalid:   ptr_color = &sp_colorset_text->color_invalid;   break;
    }
  }

  if( m_btn_type == eBtnType::Normal )
  {
    zzf_DrawText
      ( in_rect
      , m_text
      , *ptr_color
      , 0.0f
      , float2( 0, 0 )
      , DX::kFDM_X_MIDDLE | DX::kFDM_Y_MIDDLE
      );
  }
  else // Check or Radio
  {
    DX::ColorType color = ptr_color->color[0];
    float scale  = in_rect.Height();
    //float space  = scale * 0.2f;
    float size_y = scale * 0.8f;
    float4 rt_check = zzf_getCheckBoxSize_();
    rt_check.x += in_rect.x;
    rt_check.z += in_rect.x;
    rt_check.y += in_rect.y;
    rt_check.w += in_rect.y;

    if( m_btn_type == eBtnType::Check  ||  m_btn_type == eBtnType::AutoCheck )
    {
      // 枠
      zzf_DrawFrame( rt_check, color );

      if( this->GetBtnState().is_check )
      {
        DrawVtxInfo vtx[4] =
        { DrawVtxInfo{ 0.2f*scale + in_rect.x, 0.4f*scale + in_rect.y, 0.0f, color }
        , DrawVtxInfo{ 0.4f*scale + in_rect.x, 0.6f*scale + in_rect.y, 0.0f, color }
        , DrawVtxInfo{ 0.4f*scale + in_rect.x, 0.8f*scale + in_rect.y, 0.0f, color }
        , DrawVtxInfo{ 0.9f*scale + in_rect.x, 0.3f*scale + in_rect.y, 0.0f, color }
        };
        U32 idx[4] = { 0, 1, 2, 3 };
        zzf_DrawPolygon
          ( vtx, CPL_ARRAY_NUM(vtx)
          , idx, CPL_ARRAY_NUM(idx)
          , D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP
          );
      }
    }
    else
    if( m_btn_type == eBtnType::Radio  ||  m_btn_type == eBtnType::AutoRadio )
    {
      zzf_DrawCircle
        ( float2((rt_check.x+rt_check.z)*0.5f, (rt_check.y+rt_check.w)*0.5f)
        , size_y*0.4f
        , color
        , false
        );
      if( this->GetBtnState().is_check )
      {
        zzf_DrawCircle
          ( float2((rt_check.x+rt_check.z)*0.5f, (rt_check.y+rt_check.w)*0.5f)
          , size_y*0.2f
          , color
          , false
          );
        zzf_DrawCircle
          ( float2((rt_check.x+rt_check.z)*0.5f, (rt_check.y+rt_check.w)*0.5f)
          , size_y*0.19f
          , color
          , true
          );
      }
    }

    float4 rt_msg = in_rect;
    rt_msg.left = (int)rt_check.right + 5.0f;
    zzf_DrawText
      ( rt_msg
      , m_text
      , *ptr_color
      , 0.0f
      , float2( 20.0f, 0 )
      , DX::kFDM_X_LEFT | DX::kFDM_Y_MIDDLE
      );
  }
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseUp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  Button::On_MouseUp
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    , _in<eMouseButton    > in_type_mouse_btn
    )
{
  td_base::On_MouseUp( in_sp_component, in_mouse_x, in_mouse_y, in_type_mouse_btn ); // デフォルト処理呼び出し

  if( in_sp_component == this->GetLinkMyself() )
  {
    if( m_btn_type == eBtnType::AutoCheck )
    {
      m_btn_state.is_check = !m_btn_state.is_check;
    }
    else
    if( m_btn_type == eBtnType::AutoRadio )
    {
      auto sp_comp = GetLinkTop();
      while( sp_comp )
      {
        if( sp_comp != GetLinkMyself() )
        {
          if( auto ptr_btn = dynamic_cast<Button*>(sp_comp.get()) )
          {
            ptr_btn->SetBtnStateCheck( false );
          }
        }
        sp_comp = sp_comp->GetLinkNext();
      }
      SetBtnStateCheck( true );
    }

    Update();
  }

  return eEventReturnID::SendParent_Position;
}





// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @copydoc doxycomment::arg_in_position_for_component
/// @copydoc doxycomment::arg_in_size_for_component
/// @param[in] in_sp_default_texture
///   : デフォルトテクスチャビューオブジェクトを指定します。\n
///   : テクスチャID == 0で登録されます。
/// @param[in] in_string_for_tooltip
///   : マウスを置いたときに表示される説明文を指定します。\n
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ButtonImage::ButtonImage
( _in<sdptr<Component>> in_sp_component_for_parent
, _in<float2          > in_position_for_component
, _in<float2          > in_size_for_component
, _in<CpDxTexResView  > in_sp_default_texture
, pin<td_DefChar      > in_string_for_tooltip
) : Button
    ( in_sp_component_for_parent
    , in_position_for_component
    , in_size_for_component
    , CPL_GUC_DEF_STR("")
    , in_string_for_tooltip
    )
  //, m_draw_index_link_position( -1 )
  //, m_draw_state_ID( -1 )
  , m_auto_change_ID_up( -1 )
  , m_auto_change_ID_over( -1 )
  , m_auto_change_ID_down( -1 )
  , m_auto_change_ID_invalid( -1 )
{
  zzf_SetInitializedLevel( zzf_GetClassLevel() );

  m_texture_table.Add( 0, in_sp_default_texture );
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ButtonImage::ButtonImage( cref<ButtonImage> in_btn_img )
  : Button( in_btn_img )
  , m_auto_change_ID_up     ( in_btn_img.m_auto_change_ID_up )
  , m_auto_change_ID_over   ( in_btn_img.m_auto_change_ID_over )
  , m_auto_change_ID_down   ( in_btn_img.m_auto_change_ID_down )
  , m_auto_change_ID_invalid( in_btn_img.m_auto_change_ID_invalid )
  , m_color_table           ( in_btn_img.m_color_table )
  , m_draw_index_link_list  ( in_btn_img.m_draw_index_link_list )
  , m_draw_scale            ( in_btn_img.m_draw_scale )
  , m_texture_table         ( in_btn_img.m_texture_table )
  , m_uv_rect_table         ( in_btn_img.m_uv_rect_table )
{
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  ButtonImage::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
      );
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawClient
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::On_DrawClient( _in<float4> in_rect )
{
  DX::DXDevice*  ptr_d3d_dev = sm_ptr_d3ddev();
  CPL_DBG_OUTPUT_RETURN_IF( !ptr_d3d_dev, SwS(CPL_DX_MSG_NOT_DEVICE) );

  int draw_state_ID;// = m_draw_state_ID;
  bool const is_auto_state = (m_btn_state.view_state == (int)eBtnViewState::Auto);
  if( is_auto_state )
  {
    bool const is_enable = this->IsEnable();
    bool const is_mouse_over = sm_sp_ac_comp() == this->GetLinkMyself();
    if( !is_enable )
    {
      draw_state_ID = m_auto_change_ID_invalid;
    }
    else
    if( is_mouse_over )
    {
      if( !WIN::Mouse::GetDownL() ) // active
      {
        draw_state_ID = m_auto_change_ID_over;
      }
      else // highlight
      {
        draw_state_ID = m_auto_change_ID_down;
      }
    }
    else
    {
      draw_state_ID = m_auto_change_ID_up;
    }
  }
  else
  {
    switch( (eBtnViewState)m_btn_state.view_state )
    {
    //case eBtnViewState::Default:   draw_state_ID = m_auto_change_ID_up; break;
    case eBtnViewState::Active:    draw_state_ID = m_auto_change_ID_over; break;
    case eBtnViewState::HighLight: draw_state_ID = m_auto_change_ID_down; break;
    case eBtnViewState::Invalid:   draw_state_ID = m_auto_change_ID_invalid; break;
    default:
      draw_state_ID = m_auto_change_ID_up;
      break;
    }
  }

  auto itr_link_idx_array =
    m_draw_index_link_list.find( draw_state_ID );
  if( itr_link_idx_array == m_draw_index_link_list.end() )
  {
    return;
  }

  float const size_frame = GetFrameSize();

  //
  //CPL_LOOP2( link_idx_array.GetNum(), draw_idx )
  for( auto& link_indexs : itr_link_idx_array->second )
  {
    // 
    int image_idx = link_indexs.image_idx;
    int uv_idx    = link_indexs.uv_idx;
    int color_idx = link_indexs.color_idx;
    if( image_idx == (U8)-1  ||  uv_idx == (U8)-1 )
    {
      continue;
    }
    CpDxTexResView sp_tex = m_texture_table[ image_idx ];

    CDI::ColorType
      color = (color_idx == (U8)-1)
        ? kCOLOR_WHITE
        : m_color_table[ color_idx ];
    // アルファ調整
    color.a = static_cast<float>(color.a * sm_all_applied_draw_alpha());
    Clamp( color.a, 0.0f, 1.0f );

    //
    float4 rt = m_uv_rect_table[ uv_idx ];

    // 描画
    float2
      pos{ in_rect.x + size_frame + (in_rect.Width() - rt.Width() * m_draw_scale.x) * 0.5f
         , in_rect.y + size_frame + (in_rect.Height() - rt.Height() * m_draw_scale.y) * 0.5f
         };
    sm_def_sprite_mng().Draw
      ( sp_tex
      , pos
      , rt
      , 0.0f
      , color
      , float2{0,0} // center
      , m_draw_scale
      );
  }

  sm_def_sprite_mng().Transrate();
}


//// _____________________________________________________________________________
///// @copydoc CPL::GUC::MouseEventInterface::On_MouseEnter
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//eEventReturnID
//  ButtonImage::On_MouseEnter
//    ( _in<sdptr<Component>> in_sp_comp_enter
//    , _in<sdptr<Component>> in_sp_comp_leave
//    )
//{
//  if( in_sp_comp_leave == GetLinkMyself() )
//  {
//    bool const is_auto = (m_btn_state.view_state == (U32)eBtnViewState::Auto);
//    if( is_auto  &&  m_auto_change_ID_over >= 0 )
//    {
//      //SetDrawStateID( m_auto_change_ID_over );
//      Update();
//    }
//  }
//
//  return eEventReturnID::SendParent_Position;
//}
//
//
//// _____________________________________________________________________________
///// @copydoc CPL::GUC::MouseEventInterface::On_MouseLeave
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//eEventReturnID
//  ButtonImage::On_MouseLeave
//    ( _in<sdptr<Component>> in_sp_comp_leave
//    , _in<sdptr<Component>> in_sp_comp_enter
//    )
//{
//  if( in_sp_comp_leave == GetLinkMyself() )
//  {
//    bool const is_auto = (m_btn_state.view_state == (U32)eBtnViewState::Auto);
//    if( is_auto  &&  m_auto_change_ID_up >= 0 )
//    {
//      //SetDrawStateID( m_auto_change_ID_up );
//      Update();
//    }
//  }
//
//  return eEventReturnID::SendParent_Position;
//}
//
//
//// _____________________________________________________________________________
///// @copydoc CPL::GUC::MouseEventInterface::On_MouseDown
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//eEventReturnID
//  ButtonImage::On_MouseDown
//    ( _in<sdptr<Component>> in_sp_component
//    , _in<float           > in_mouse_x
//    , _in<float           > in_mouse_y
//    , _in<eMouseButton    > in_type_mouse_btn
//    )
//{
//  if( in_sp_component == GetLinkMyself() )
//  {
//    ActivateTopOrder();
//  
//    bool const is_auto = (m_btn_state.view_state == (U32)eBtnViewState::Auto);
//    if( is_auto  &&  m_auto_change_ID_down >= 0 )
//    {
//      //SetDrawStateID( m_auto_change_ID_down );
//      Update();
//    }
//  }
//  
//  return eEventReturnID::SendParent_Position;
//}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseUp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ButtonImage::On_MouseUp
  ( _in<sdptr<Component>> in_sp_component
  , _in<float           > in_mouse_x
  , _in<float           > in_mouse_y
  , _in<eMouseButton    > in_type_mouse_btn
  )
{
  if( in_sp_component == GetLinkMyself() )
  {
    bool const is_auto = (m_btn_state.view_state == (U32)eBtnViewState::Auto);
    if( is_auto  &&  m_auto_change_ID_over >= 0 )
    {
      //SetDrawStateID( m_auto_change_ID_over );
      Update();
    }
  }

  return eEventReturnID::SendParent_Position;
}



// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// IDインデックステーブル設定簡易化用関数
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void ButtonImage::zzf_setIDTable_(
//  ID_Idx*         out_idx_table,
//  ID_Info const*  in_ID_table,
//  const U16       in_table_num )
//{
//  const int num = Min<int>( 4, in_table_num );
//  int idx = 0;
//  for(; idx < num; ++idx )
//  {
//    int img_id = in_ID_table[ idx ].image_ID;
//    int uv_id  = in_ID_table[ idx ].rect_ID;
//
//    // 検索
//    out_idx_table[ idx ].image_idx = (U8)m_texture_table.FindIndex( img_id );
//    out_idx_table[ idx ].uv_idx    = (U8)m_uv_rect_table.FindIndex( uv_id );
//  }
//  if( idx < 3 ) // 最大数に達していなかったら、終端用の値を設定する。
//  {
//    m_up_ID[ idx ] = ID_Idx();
//  }
//}


//// _____________________________________________________________________________
///// @copydoc Button::SetBtnStateView
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void ButtonImage::SetBtnStateView( eBtnViewState in_state_view )
//{
//  td_base::SetBtnStateView( in_state_view );
//
//  switch( in_state_view )
//  {
//  case eBtnViewState::Auto:
//    break;
//  case eBtnViewState::Default:
//    m_btn_state.view_state = m_auto_change_ID_up;
//    break;
//  case eBtnViewState::Active:
//    m_btn_state.view_state = m_auto_change_ID_over;
//    break;
//  case eBtnViewState::HighLight:
//    m_btn_state.view_state = m_auto_change_ID_down;
//    break;
//  case eBtnViewState::Invalid:
//    m_btn_state.view_state = m_auto_change_ID_invalid;
//    break;
//  }
//}


// _____________________________________________________________________________
/// @brief 描画ステートIDと各IDとのリンク設定
/// 
/// @param[in] in_draw_state_ID : 識別用のイメージステートIDを指定します。
/// @param[in] in_tbl_linkIDs   : LinkIDsテーブルの先頭アドレスを指定します。
/// @param[in] in_num_linkIDs   : in_tbl_linkIDsの要素数を指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  ButtonImage::AddDrawStateLink
    ( _in<int    > in_draw_state_ID
    , pin<LinkIDs> in_tbl_linkIDs
    , _in<size_t > in_num_linkIDs
    )
{
  auto& arr_linkIdxs = m_draw_index_link_list[ in_draw_state_ID ];
  arr_linkIdxs.clear();

  for
    ( size_t idx_LIDs = 0
    ; idx_LIDs < in_num_linkIDs
    ; ++idx_LIDs
    )
  {
    LinkIDs const& lid = in_tbl_linkIDs[ idx_LIDs ];
    LinkIndexs lis;
    lis.image_idx = static_cast<U8>(m_texture_table.FindIndex( lid.image_ID ));
    lis.uv_idx    = static_cast<U8>(m_uv_rect_table.FindIndex( lid.rect_ID  ));
    lis.color_idx = static_cast<U8>(m_color_table  .FindIndex( lid.color_ID ));

    //
    arr_linkIdxs.push_back( lis );
  }
}


//// _____________________________________________________________________________
///// @brief イメージステートの設定
///// 
///// @param[in] in_draw_state_ID : 使用するイメージステートのIDを指定します。
///// 
///// @retval true  : ID該当あり。
///// @retval false : ID該当なし。
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//bool ButtonImage::SetDrawStateID( _in<int> in_draw_state_ID ) noexcept
//{
//  auto itr_hit = m_draw_index_link_list.find( in_draw_state_ID );
//  if( itr_hit != m_draw_index_link_list.end() )
//  {
//    m_draw_state_ID = in_draw_state_ID;
//    return true;
//  }
//  return false;
//}


// _____________________________________________________________________________
/// @brief 自動イメージ切り替え設定
/// 
/// @param[in] in_image_state_ID_up
///   : アップ状態のイメージステートIDを指定します。\n
///   : 変更しない場合は-1を指定します。
/// @param[in] in_image_state_ID_over
///   : マウスがボタンの上にある状態時のイメージステートIDを指定します。\n
///   : 変更しない場合は-1を指定します。
/// @param[in] in_image_state_ID_down
///   : ダウン状態のイメージステートIDを指定します。\n
///   : 変更しない場合は-1を指定します。
/// @param[in] in_image_state_ID_invalid
///   : 無効状態のイメージステートIDを指定します。\n
///   : 変更しない場合は-1を指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  ButtonImage::SetAutoChangeImageState
    ( _in<int> in_image_state_ID_up
    , _in<int> in_image_state_ID_over
    , _in<int> in_image_state_ID_down
    , _in<int> in_image_state_ID_invalid
    )
{
  m_auto_change_ID_up      = in_image_state_ID_up;
  m_auto_change_ID_over    = in_image_state_ID_over;
  m_auto_change_ID_down    = in_image_state_ID_down;
  m_auto_change_ID_invalid = in_image_state_ID_invalid;
}


// _____________________________________________________________________________
/// @brief 関連付けイメージの追加
/// 
/// @param[in] in_image_ID
///   : 追加するイメージの識別IDを指定します。
/// @param[in] in_sp_texview
///   : 追加イメージとなるテクスチャリソースビューを指すスマートポインタを指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void
  ButtonImage::AddImage
    ( _in<int           > in_image_ID
    , _in<CpDxTexResView> in_sp_texview
    )
{
  m_texture_table.Add( in_image_ID, in_sp_texview );
}


// _____________________________________________________________________________
/// @brief イメージの登録抹消
/// 
/// @param[in] in_image_ID
///   : 登録を抹消するイメージのステートIDを指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::DelImage( _in<int> in_image_ID )
{
  m_texture_table.Delete( in_image_ID );
}


// _____________________________________________________________________________
/// @brief 矩形情報の追加
/// 
/// @param[in] in_uv_ID : 追加する矩形座標の識別IDを指定します。
/// @param[in] in_rect  : 追加する矩形座標を指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::AddRect( _in<int> in_uv_ID, _in<float4> in_rect )
{
  m_uv_rect_table.Add( in_uv_ID, &in_rect );
}


// _____________________________________________________________________________
/// @brief 矩形情報の削除
/// 
/// @param[in] in_uv_ID : 削除する矩形情報の識別IDを指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::DelRect( _in<int> in_uv_ID )
{
  m_uv_rect_table.Delete( in_uv_ID );
}


// _____________________________________________________________________________
/// @brief カラー情報の追加
/// 
/// @param[in] in_color_ID : 追加するカラーの識別IDを指定します。
/// @param[in] in_color : 追加するカラーをCDI::ColorType形式で指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::AddColor( _in<int> in_color_ID, _in<CDI::ColorType> in_color )
{
  m_color_table.Add( in_color_ID, in_color );
}


// _____________________________________________________________________________
/// @brief カラー情報の削除
/// 
/// @param[in] in_color_ID : 削除するカラーの識別IDを指定します。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ButtonImage::DelColor( _in<int> in_color_ID )
{
  m_color_table.Delete( in_color_ID );
}


} // namespace GUC
} // namespace CPL

