/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   2010/X/X - 2017/02/01
/// 
/// @brief  アクティブメニューコンポーネント。
/// 
/// ****************************************************************************


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


#include "CPL_GUC_ActiveMenu.h"


namespace CPL {
namespace GUC {



// _____________________________________________________________________________
/// @brief メニューのデフォルト背景カラー
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet>
  ActiveMenu::GetDefaultColor_MenuBG()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicBG()
        );
  return sp_color;
}


// _____________________________________________________________________________
/// @brief デフォルトフレームカラー
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet>
  ActiveMenu::GetDefaultColor_MenuFrame()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicFrame()
        );
  return sp_color;
}


// _____________________________________________________________________________
/// @brief デフォルトテキストカラー
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<DrawColorSet>
  ActiveMenu::GetDefaultColor_MenuText()
{
  static auto
    sp_color =
      CPL_MAKE_SHARED
        ( DrawColorSet
        , ColorPattern::DynamicText()
        );
  return sp_color;
}


// _____________________________________________________________________________
/// @brief 拡張メニューフォームクラス
///
// *****************************************************************************
class MenuFormEx
  : public Container
{
  using td_base = Container;
  using td_self = MenuFormEx;
  friend Factory<td_self>;
  friend CallPrivateConstructor<td_self>;

  static int zzf_GetClassLevel(){ return td_base::zzf_GetClassLevel() + 1; }

protected:
  MenuFormEx
  ( _in<sdptr<Component>> in_sp_component_for_parent
  , _in<float2          > in_position_for_component
  , _in<float2          > in_size_for_component
  ) : Container
      ( in_sp_component_for_parent
      , in_position_for_component
      , in_size_for_component
      )
  {
    zzf_SetInitializedLevel( zzf_GetClassLevel() );

    //SetColorParameterBG( sp_default_menu_bg_color );
    //SetColorParameterFrame( sp_default_menu_frame_color );
    //SetColorParameterText( sp_default_menu_text_color );
  }
  MenuFormEx( cref<MenuFormEx> in_menu_form_ex )
    : td_base( in_menu_form_ex )
  {
  }
public:
  ~MenuFormEx(){}

  void On_DrawBackground( _in<float4> in_rect ) override
  {
    zzf_DrawRect( in_rect, DX::ColorType(0.25f,0.25f,0.25f, 0.25f) );
    //Component::On_DrawBackground( in_rect );
  }

  void On_DrawFrame( _in<float4> in_rect ) override
  {
//    return Component::On_DrawFrame( in_rect );
    zzf_DrawFrame( in_rect, DX::ColorType(1.0f,1.0f,1.0f, 0.5f) );
    //Component::On_DrawFrame( in_rect );
  }

  // _____________________________________________________________________________
  /// @copydoc CPL::GUC::Component::On_UserProc
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  virtual eEventReturnID
    On_UserProc
      ( _in<sdptr<Component>> in_sp_component
      , _in<long            > in_message
      , _in<WPARAM          > in_wparam
      , _in<LPARAM          > in_lparam
      )
  {
    return eEventReturnID::SendParent_All;
  }

  //void
  //  SetupBelongComponent_for_Rendering
  //    ( _in<sdptr<Component>> io_sp_comp_belong
  //    ) noexcept
  //{
  //  Component::SetBelongComponent
  //    ( io_sp_comp_belong
  //    , eParentType::Render
  //    );
  //}

  // _____________________________________________________________________________
  /// @copydoc CPL::GUC::Component::CreateClone
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  sdptr<Component>
    CreateClone
      ( _in<sdptr<Component>> in_sp_component_for_parent       = nullptr
      , _in<float2          > in_offset_position_from_original = float2{0,0}
      ) const override
  {
    return
      zzz_CreateClone_Basic<td_self>
        ( in_sp_component_for_parent
        , in_offset_position_from_original
        );
  }
};


// _____________________________________________________________________________
/// @brief コンストラクタ
/// 
/// @copydoc doxycomment::arg_in_sp_component_for_parent
/// @param[in] in_rect_for_menuview
///   : メニューの表示矩形をfloat4で指定します。
/// @param[in] in_string_for_menu
///   : メニューの表示文字列を指定します。
/// @param[in] in_menu_ID
///   : メニューＩＤを指定します。
/// @param[in] in_mode_list
///   : リスト配置設定１。詳しくはActiveMenu::eListMode参照してください。
/// @param[in] in_pos_mode
///   : 表示位置設定２。詳しくはActiveForm::ePosMode参照してください。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveMenu::ActiveMenu
( _in<sdptr<Component>    > in_sp_component_for_parent
, _in<float4              > in_rect_for_menuview
, _in<td_DefString        > in_string_for_menu
, _in<int                 > in_menu_ID
, _in<eListMode           > in_mode_list
, _in<ActiveForm::ePosMode> in_pos_mode
) : td_base
    ( in_sp_component_for_parent
    , float2( in_rect_for_menuview.x, in_rect_for_menuview.y )
    , in_string_for_menu
    , Factory<MenuFormEx>::Create
      ( in_sp_component_for_parent
      , kPOS_DEFAULT
      , float2( in_rect_for_menuview.Width()
              , in_rect_for_menuview.Height()
              )
      ) // 子メニュー配置フォームとなる
    , -1
    , in_pos_mode
    )
  , m_menu_ID( in_menu_ID )
  , m_flag_check( false )
  , m_flag_select( false )
  , m_flag_listmode( in_mode_list )
{
  //if( !(in_mode_list & eListMode::Fixed) )
  //{
  //  m_flag_expand = 0;
  //}
  m_flag_expand = (in_mode_list & eListMode::Fixed) != 0;

  //
  m_sp_item_container->SetPosition( float2{0, 0} );

  if( m_menu_ID >= 0 )
  {
    // アイテムフォームの親変更（アクティブの子供ノードに移動）
    auto sp_active_form = m_wp_active_form.lock();
    m_sp_item_container->SetBelongComponent
      ( sp_active_form
      , eParentType::All
      );
  }
//  if( in_mode_list & LISt_FIXED )
//  {
  this->SetRectCoord( in_rect_for_menuview );

  m_sp_item_container->SetStateVisible( true );
  SetStateVisible( true );
//  }

  // 描画ステートのデフォルト設定。
  if( m_menu_ID == 0 )
  {
    zzf_setupDrawState( false, false, false );
  }
  else
  {
    zzf_setupDrawState( true, true, true );
  }

  zzf_SetInitializedLevel( zzf_GetClassLevel() );

  //SetTimer( 0, 200 );
}


// _____________________________________________________________________________
/// @brief コピーコンストラクタ
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ActiveMenu::ActiveMenu( cref<ActiveMenu> in_active_menu )
  : td_base( in_active_menu )
  , m_menu_ID      ( in_active_menu.m_menu_ID       )
  , m_flag_check   ( in_active_menu.m_flag_check    )
  , m_flag_select  ( in_active_menu.m_flag_select   )
  , m_flag_listmode( in_active_menu.m_flag_listmode )
  , m_explanation  ( in_active_menu.m_explanation   )
{
}


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




// _____________________________________________________________________________
/// @brief アイテム追加
/// 
/// @param[in] in_create_info
///   : アイテム情報構造体を指定します。\n
///   : 詳しくはCreateItemInfoを参照してください。
/// 
/// @return 新しく作成されたメニューのスマートポインタを指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu>
  ActiveMenu::InsertItem
    ( _in<CreateItemInfo> in_create_info
    )
{
  m_menu_ID = -Abs(m_menu_ID); // 子供を持つと、in_menu_IDをマイナスにする。

  auto size_client = GetSize();
  auto const height_line = sm_def_font_mng()->GetFont()->GetHeight() + 6; //Component::GetLineHeight();
  int x = 0, y = 0;
  float4 rt( 0, 0, 100, static_cast<float>(height_line) ); // 仮の位置を設定。
  
  if( in_create_info.in_ptr_rect ) // 矩形指定があれば設定する。
  {
    rt = *in_create_info.in_ptr_rect;
  }
  // リスト配置補正。
  eListMode list_mode = GetListMode();
  if( list_mode & eListMode::Fixed ) // 固定モードの場合。
  {
    // 自身のサイズ調整。
    SetSize( float2(rt.z, rt.w) );
  }
  else // 固定モードではない場合。
  {
    auto sp_active_form = GetComponent_ActiveForm();
    auto sp_item_comp   = m_sp_item_container;

    if( list_mode & eListMode::AutoVertical ) // 自動縦リストモードの場合。
    {
      // 横幅は固定で設定。
      rt.x = 0;
      rt.z = sp_active_form->GetSize().x;

      auto sp_menu_child = sp_item_comp->GetLinkChild();
      auto sp_menu_child_end =
        sp_menu_child ? sp_menu_child->GetLinkEnd()
                      : nullptr;
      if( sp_menu_child_end )
      {
        rt.y = sp_menu_child_end->GetRectCoord().w;
        rt.w += rt.y;
      }
      else
      {
        rt.y = 0;
      }
      rt.w = rt.y + height_line;
    }
    else
    if( list_mode & eListMode::AutoHorizontal ) // 自動横リストモードの場合。
    {
      // 縦幅は固定で設定。
      rt.y = 0;
      rt.w = static_cast<float>(height_line);
      
      auto sp_menu_child = sp_item_comp->GetLinkChild();
      auto sp_menu_child_end =
        sp_menu_child ? sp_menu_child->GetLinkEnd()
                      : nullptr;
      if( sp_menu_child_end )
      {
        rt.x = sp_menu_child_end->GetRectCoord().z;
        rt.z += rt.x;
      }
      else
      {
        rt.x = 0;
      }
    //#ifdef CPL_UNICODE
      auto size =
        sm_def_font_mng()->GetStringLineSize
          ( in_create_info.in_string
          , 0
          , nullptr
          );
    //#else
    //  Core::StringW strw;
    //  Core::ChangeCodeStrings( strw, in_str );
    //  auto size = sm_def_font_mng()->GetStringLineSize( strw, 0, nullptr );
    //#endif
      rt.z = rt.x + size.x;
    }
  }

  // 配置フラグがデフォルトの場合、フラグを調整する。
  auto flag_listmode_item = in_create_info.in_mode_list;
  auto flag_pos_item      = in_create_info.in_mode_pos;
  if( flag_listmode_item == eListMode::Default )
  {
    auto flag_listmode_myself
      = GetListMode(); // リスト配置モードを取得。
    auto flag_pos_myself
      = GetComponent_ActiveForm()->GetPosMode(); // 位置フラグを取得。
    bool is_pos_default
      = in_create_info.in_mode_pos == ActiveForm::ePosMode::Default;
    switch( flag_listmode_myself & 0xf )
    {
    case eListMode::AutoVertical: // 自動縦リスト。
      flag_listmode_item = eListMode::AutoVertical;
      flag_pos_item =
        is_pos_default ? ActiveForm::ePosMode::RightLower
                       : in_create_info.in_mode_pos;
      break;
    case eListMode::AutoHorizontal: // 自動横リスト。
      flag_listmode_item = eListMode::AutoVertical;
      flag_pos_item =
        is_pos_default ? ActiveForm::ePosMode::BottomRightSide
                       : in_create_info.in_mode_pos;
      break;
    case eListMode::OriginalPosition: // 位置指定。
      flag_listmode_item = eListMode::OriginalPosition;
      break;
    }
  }

  // 新しいメニューの作成
  auto sp_ac_menu =
    Factory<ActiveMenu>::Create
      ( m_sp_item_container // m_wp_item_containerは必ず作成されていること。
      , rt
      , in_create_info.in_string
      , in_create_info.in_menu_ID
      , flag_listmode_item
      , flag_pos_item
      );
  sp_ac_menu->SetExplanation( in_create_info.in_explanation );
  if( in_create_info.in_user_ID != "" )
  {
    sp_ac_menu->SetUserID( in_create_info.in_user_ID );
  }
  
  // テーブルに追加
  m_child_menu_table.push_back( sp_ac_menu );

  // フォームサイズ調整
//  m_sp_item_comp->AdjustSize();
//  m_sp_active_form->AdjustSize();
//  AutoRepositionItems( 0, 0 );

  return sp_ac_menu;
}


// _____________________________________________________________________________
/// @brief 親メニューの取得
/// 
/// @return 親メニューコンポーネントのスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::GetMenu_Parent() const
{
  auto sp_comp_parent = GetBelongComponent( eParentType::Position );
  while( sp_comp_parent )
  {
    auto sp_menu_parent = std::dynamic_pointer_cast<ActiveMenu>(sp_comp_parent);
    if( sp_menu_parent )
    {
      return sp_menu_parent;
    }

    sp_comp_parent = sp_comp_parent->GetBelongComponent( eParentType::Position );
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 親メニューの取得
/// 
/// @return ルートメニューコンポーネントのスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::GetMenu_Root() const
{
  auto sp_menu_parent = GetMenu_Parent();
  while( sp_menu_parent )
  {
    if( auto sp_menu_parent2 = sp_menu_parent->GetMenu_Parent() )
    {
      sp_menu_parent = sp_menu_parent2;
      continue;
    }
    return sp_menu_parent;
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 前方のメニューの取得
/// 
/// @return
/// 前方のメニューのスマートポインタを返します。\n
/// 前方にメニューがない場合nullptrを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::GetMenu_Prev() const
{
  auto sp_prev = GetLinkPrev();
  while( sp_prev )
  {
    if( auto sp_menu_next = std::dynamic_pointer_cast<ActiveMenu>(sp_prev) )
    {
      return sp_menu_next;
    }
    sp_prev = sp_prev->GetLinkPrev();
  }
  return nullptr;
}

// _____________________________________________________________________________
/// @brief 後方のメニューの取得
/// 
/// @return
/// 後方のメニューのスマートポインタを返します。\n
/// 後方にメニューがない場合nullptrを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::GetMenu_Next() const
{
  auto sp_next = GetLinkNext();
  while( sp_next )
  {
    if( auto sp_menu_next = std::dynamic_pointer_cast<ActiveMenu>(sp_next) )
    {
      return sp_menu_next;
    }
    sp_next = sp_next->GetLinkNext();
  }
  return nullptr;
}

// _____________________________________________________________________________
/// @brief 子供メニューの先頭の取得
/// 
/// @return 子供メニューの先頭のメニューのスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::GetMenu_Child() const
{
  if( m_child_menu_table.empty() )
  {
    return nullptr;
  }
  return m_child_menu_table[0];
}


// _____________________________________________________________________________
/// @brief 淡色設定
/// 
/// @param[in] in_menu_ID : 設定するメニューのID.
/// @param[in] in_flag_enable
///   : true  - 淡色化する。\n
///   : false - 淡色化しない（通常表示）。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::SetMenuItemEnable( _in<int> in_menu_ID, _in<int> in_flag_enable )
{
  if( auto sp_ac_menu = FindMenu_by_ID( in_menu_ID ) )
  {
    sp_ac_menu->SetStateEnable( in_flag_enable != 0 );
    sp_ac_menu->Update();
  }
}


// _____________________________________________________________________________
/// @brief チェック設定
/// 
/// @param[in] in_menu_ID : 設定するメニューのID.
/// @param[in] in_flag_check
///   : true  - チェックを入れる。\n
///   : false - チェックを入れない。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::SetMenuItemCheck( _in<int> in_menu_ID, _in<int> in_flag_check )
{
  if( auto sp_ac_menu = FindMenu_by_ID( in_menu_ID ) )
  {
    sp_ac_menu->SetFlag_Check( in_flag_check != 0 );
    sp_ac_menu->Update();
  }
}

// _____________________________________________________________________________
/// @brief 選択スタイルフラグ設定
/// 
/// @param[in] in_menu_ID : 設定するメニューのID.
/// @param[in] in_flag_select
///   : true  - 選択状態にする。\n
///   : false - 選択状態にしない（通常の状態）。
/// 
/// @return なし。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::SetMenuItemSelect( _in<int> in_menu_ID, _in<int> in_flag_select )
{
  if( auto sp_ac_menu = FindMenu_by_ID( in_menu_ID ) )
  {
    sp_ac_menu->SetFlag_Select( in_flag_select != 0 );
    sp_ac_menu->Update();
  }
}

//// _____________________________________________________________________________
///// @brief 拡張スタイルの設定
///// 
///// @param[in] in_menu_ID : 設定するメニューのID.
///// @param[in] in_flag_ex_style
/////   : 
///// 
///// @return なし。
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void ActiveMenu::SetMenuItemExStyle( _in<int> in_menu_ID, _in<int> in_flag_ex_style )
//{
//  if( auto sp_ac_menu = FindMenu( in_menu_ID ) )
//  {
//    sp_ac_menu->SetFlag_Select( in_flag_ex_style != 0 );
//    sp_ac_menu->Update();
//  }
//}


// _____________________________________________________________________________
/// @brief コンポーネントIDによるメニューの検索
/// 
/// @param[in] in_menu_ID : メニューのIDを指定します。
/// 
/// @return
/// ヒットしたメニューコンポーネントのスマートポインタを返します。\n
/// 該当しない場合、nullptrを表すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::FindMenu_by_ID( _in<int> in_menu_ID ) const
{
  if( Abs(m_menu_ID) == in_menu_ID )
  {
    return GetLinkMyself<ActiveMenu>();
  }

  // 検索
  for( auto sp_active_menu : m_child_menu_table )
  {
    auto sp_menu_hit = sp_active_menu->FindMenu_by_ID( in_menu_ID );
    if( sp_menu_hit )
    {
      return sp_menu_hit;
    }
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief ユーザーIDによるメニューの検索
/// 
/// @param[in] in_user_ID : メニューに割り当てられているユーザーIDを指定します。
/// 
/// @return
/// ヒットしたメニューコンポーネントのスマートポインタを返します。\n
/// 該当しない場合、nullptrを表すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::FindMenu_by_UserID( _in<std::string> in_user_ID ) const
{
  if( GetUserID() == in_user_ID )
  {
    return GetLinkMyself<ActiveMenu>();
  }

  // 検索
  for( auto sp_active_menu : m_child_menu_table )
  {
    auto sp_menu_hit = sp_active_menu->FindMenu_by_UserID( in_user_ID );
    if( sp_menu_hit )
    {
      return sp_menu_hit;
    }
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief 名前によるメニューの検索
/// 
/// @param[in] in_name : メニューの名前を指定します。
/// 
/// @return
/// ヒットしたメニューコンポーネントのスマートポインタを返します。\n
/// 該当しない場合、nullptrを表すスマートポインタを返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<ActiveMenu> ActiveMenu::FindMenu_by_Name( _in<td_DefString> in_name ) const
{
  auto sp_menu = std::dynamic_pointer_cast<ActiveMenu>(GetLinkMyself());
  while( sp_menu )
  {
    if( sp_menu->GetText() == in_name )
    {
      return sp_menu;
    }

    if( auto sp_menu_child = sp_menu->GetMenu_Next() )
    {
      if( auto sp_menu_hit = sp_menu->FindMenu_by_Name( in_name ) )
      {
        return sp_menu_hit;
      }
    }

    sp_menu = sp_menu->GetMenu_Next();
  }

  return nullptr;
}


// _____________________________________________________________________________
/// @brief アクティブフォームの階層検索
/// 
/// @param[in] in_ptr_form : 対象とするアクティブフォームのポインタを指定する。
/// 
/// @return
/// 指定されたアクティブフォームを保持する場合（子供を含む）、そのアクティブ
/// フォームまでの階層数を取得。\n
/// 該当しない場合−１を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int ActiveMenu::FindActiveForm( pin<ActiveForm> in_ptr_form ) const
{
  if( in_ptr_form == nullptr
   || this->GetComponent_ActiveForm() == in_ptr_form->GetLinkMyself() )
  {
    return 0;
  }

  for( auto sp_active_menu : m_child_menu_table )
  {
    int ret = sp_active_menu->FindActiveForm( in_ptr_form );
    if( ret >= 0 )
    {
      return ret + 1;
    }
  }

  return -1;
}

/*
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// アクティブなフォームのポインタを設定する
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::SetActiveFormSmPtr( SmPtr in_sp_ac_form )
{
  m_sp_active_form = in_sp_ac_form;
}*/

// _____________________________________________________________________________
/// @brief アイテムの再配置
/// 
/// 子供メニューを整地する。\n
/// 自身の配置は親が決めるので設定しない。\n
/// ただし、自身のアイテムフォームの親は設定する。
/// 
/// @return 整列後の縦幅を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float ActiveMenu::AutoRepositionItems()
{
  bool const is_child      = !m_child_menu_table.empty();
  bool const is_child_view = is_child  &&  GetFlag_Expand() != 0;

  if( !is_child )
  {
    if( m_menu_ID != 0 )
    {
      AdjustSize( float2{0,0}, GetFlag_Expand() != 0 );
    }
    return GetSize().y;
  }

  float4 rect_prev{0,0,0,0};
  // 子メニューの整地
  for( auto sp_menu : m_child_menu_table )
  {
    auto text = sp_menu->GetText();
    bool const is_separator = text.Comp( CPL_GUC_DEF_STR("_") ) == 0; // アンダースコアは区切り線とする。

    if( is_separator )
    {
      sp_menu->SetStateVisible( false );
      if( m_flag_listmode & eListMode::AutoVertical )
      {
        rect_prev.y = rect_prev.w;
        rect_prev.w = rect_prev.y + 5;
      }
      else
      if( m_flag_listmode & eListMode::AutoHorizontal )
      {
        rect_prev.x = rect_prev.w;
        rect_prev.z = rect_prev.x + 5;
      }
      sp_menu->SetRectCoord( rect_prev );
    }
    else
    {
      sp_menu->AutoRepositionItems();
      auto rect_child = sp_menu->GetRectCoord();
      // 自動縦リスト配置モードの場合。
      if( m_flag_listmode & eListMode::AutoVertical )
      {
        if( m_menu_ID != 0 )
        {
          auto size_this = this->GetSize();
          if( rect_child.z < size_this.x )
          {
            rect_child.x = size_this.x;
          }
        }
        //
        sp_menu->SetPosition( float2{rect_prev.x, rect_prev.w} );
      }
      else
      // 横リスト自動配置モードの場合。
      if( m_flag_listmode & eListMode::AutoHorizontal )
      {
        //auto size_adj_item = sp_menu->GetAdjustSize( false );
        sp_menu->SetPosition( float2{rect_prev.z, rect_prev.y} );
      }

      // 現在のメニューの座標を保存。
      sp_menu->GetRectCoord( rect_prev );
    }
  }

  //*** アイテムフォームの配置設定 ***//

  if( m_menu_ID == 0 )
  {
    // アイテム保持コンテナを自身に移動
    m_sp_item_container->SetBelongComponent
      ( GetComponent_ActiveForm()
      , eParentType::All
      );
  }
  else
  {
    if( m_flag_expand == 1 ) // アイテムが自身内に展開されている場合。
    {
      // アイテム保持コンテナを自身に移動
      m_sp_item_container->SetBelongComponent
        ( GetLinkMyself()
        , eParentType::All
        );
      if( this->m_text == CPL_GUC_DEF_STR("") )
      {
        m_sp_item_container->SetPosition( kPOS_DEFAULT );
      }
      else
      {
        m_sp_item_container->SetPosition
          ( float2{ 5, this->GetMenuLineHeight() }
          );
      }
      m_sp_item_container->SetStateVisible( true );
      m_sp_item_container->SetStateDrawFrame( true );
      m_wp_active_form.lock()->SetStateVisible( false );
    }
    else // アイテムが自身内に展開されていない場合。
    {
      // コンテナをアクティブビューに移動
      auto sp_active_form = m_wp_active_form.lock();
      m_sp_item_container->SetBelongComponent
        ( sp_active_form
        , eParentType::All
        );
      m_sp_item_container->SetPosition( float2{0, 0} );
      sp_active_form->AdjustSize();
      //sp_active_form->SetStateDrawFrame( true );
    }
  }

  // サイズアジャスト
  // ※ サイズ変更で子メニューも自動でサイズ変更される。
  if( !m_sp_item_container->AdjustSize() )
  {
    // サイズ変更がなくても、サイズ変更イベントを呼ぶ。
    // ※ サイズ変更なしだと呼ばれないので。
    call_On_Size( m_sp_item_container );
  }

  if( m_menu_ID != 0 )
  {
    AdjustSize( float2{0,0}, GetFlag_Expand() != 0 );
  }

  return GetSize().y;
}


// _____________________________________________________________________________
/// @brief 子供メニューの最低必要幅の取得
/// 
/// @param[in] in_is_include_child : 子供メニューを含めるかどうかを指定します。
/// @param[in] in_min_width        : 最低幅を指定します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float
  ActiveMenu::GetMenuWidth
    ( _in<bool > in_is_include_child
    , _in<float> in_min_width
    ) const
{
  return Max<float>( GetAdjustSize(in_is_include_child).x, in_min_width );
}


// _____________________________________________________________________________
/// @brief メニューの縦幅の取得
/// 
/// @return メニューの縦幅を返します。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float
  ActiveMenu::GetMenuLineHeight() const
{
  float const fw = IsDrawFrame() ? GetFrameSize() : 0;
  auto const  sp_font_mng = sm_def_font_mng();
  auto const  height_font = sp_font_mng->GetFont()->GetHeight();
  return height_font + (kSPACE + fw) * 2;
}


// _____________________________________________________________________________
/// @brief フォームの最小サイズを求める
/// 
/// ヌル文字の場合、幅０、縦１ラインのサイズを返すものとする。
/// 固定モードの場合、現在のサイズをそのまま返す。
/// 
/// @param[in] in_flag_show
///   : 子供を含めるかどうか。\n
///   : true  - 含める。\n
///   : false - 含めない。
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
float2 ActiveMenu::GetAdjustSize( _in<BOOL> in_flag_show ) const noexcept
{
  //if( m_flag_listmode & eListMode::Fixed )
  //{
  //  return GetSize();
  //}
  if( m_text == CPL_GUC_DEF_STR("_") )
  {
    return float2{ 1, 5 };
  }

  float const fw = IsDrawFrame() ? GetFrameSize() : 0;
  auto const  sp_font_mng = sm_def_font_mng();
  auto const  size_text   = sp_font_mng->GetStringLineSize( m_text, 0, nullptr );
  auto const  height_line = GetMenuLineHeight();
  int text_width = size_text.x;
  float2 size{ 0, height_line };

  if( text_width > 0 ) // 文字列ありの場合。
  {
    size.x += fw + kSPACE + kSPACE_CHECK + text_width + kSPACE_ARROW + kSPACE + fw;
  }

  if( in_flag_show ) // 子供を含める場合
  {
//    if( m_flag_expand == 1 )
//    {
//      size.x += 5; // 展開される場合、オフセットとして+5されるので、その分を追加
//    }

    // 子供の数だけループ
    //size_t child_num = m_child_menu_table.GetNum();
    //CPL_LOOP2( child_num, menu_idx )
    //for( size_t menu_idx = 0; menu_idx < child_num; ++menu_idx )
    for( auto sp_menu : m_child_menu_table )
    {
      auto size_adj = sp_menu->GetAdjustSize( sp_menu->GetFlag_Expand() != 0 );
      // 自動縦リストモードの場合
      if( m_flag_listmode & eListMode::AutoVertical )
      {
        size.x = Max(size.x, size_adj.x);
        size.y += size_adj.y;
      }
      else
      // 自動横リストモードの場合
      if( m_flag_listmode & eListMode::AutoHorizontal )
      {
        size.x += size_adj.x;
      }
    }
  }

  return size;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::CreateClone
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sdptr<Component>
  ActiveMenu::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_MouseDown
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::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() )
  {
    KillTimer( eID::Tid_MouseEnterDelay );
    KillTimer( eID::Tid_MouseLeaveDelay );
    ActivateTopOrder();

    if( this->GetMenuID() == 0 )
    {
      CPL_SAFE_PTR( GetComponent_ActiveForm() )->SetStateVisible( false );
      //SetStateVisible( false );
      DetachAll();
    }
    else
    {
      if( in_type_mouse_btn == eMouseButton::Left
       && !this->m_child_menu_table.empty() )
      {
        if( m_flag_expand == 0 )
        {
          // 子供メニューを表示
          CPL_SAFE_PTR( GetComponent_ActiveForm() )->SetStateVisible( true );
        }
      }
    }
  }

  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_MouseUp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::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 == this->GetLinkMyself() )
  {
    auto sp_menu_parent = GetMenu_Parent();// 親コンポーネントを取得しておく。

    if( m_child_menu_table.empty() ) // 子供がいない場合。
    {
      if( in_type_mouse_btn == WIN::Component::eMouseButton::Left )
      {
        sdptr<Component> sp_comp_parent( sp_menu_parent );
        // ここが処理される場合、メニュー項目が選択されたことを意味する。
        // なので、現在表示中のアクティブフォームを全て非表示にする。
        while( sp_comp_parent )
        {
          ActiveMenu* ptr_menu_parent =
            dynamic_cast<ActiveMenu*>(&*sp_comp_parent);
          if( ptr_menu_parent )
          {
            ptr_menu_parent->GetComponent_ActiveForm()->SetStateVisible( false );
            if( ptr_menu_parent->GetMenuID() == 0 )
            {
              ptr_menu_parent->SetStateVisible( false );
            }
            sp_comp_parent = ptr_menu_parent->GetMenu_Parent();
          }
          else
          {
            sp_comp_parent = sp_comp_parent->GetBelongComponent( eParentType::Position );
          }
        }
        SendParentMessage
          ( GetLinkMyself(), WM_COMMAND, m_menu_ID, 0
          , eParentType::Position
          );
      }
    }
    else                  // 子供がある、かつ
    if( sp_menu_parent )  // 親メニューがある場合。
    {
      if( in_type_mouse_btn == WIN::Component::eMouseButton::Right )
      {
        if( !(sp_menu_parent->GetListMode() & eListMode::AutoHorizontal)
         && !(GetListMode() & eListMode::Fixed) )
        {
          // フォームの開閉を切り替える。
          m_flag_expand = !m_flag_expand;  // フラグを変更し、
          GetMenu_Root()->AutoRepositionItems(); // 

          if( m_flag_expand == 0 ) // 自身のクライアントに展開しない場合。
          {
            // 子供メニューを表示
            CPL_SAFE_PTR( GetComponent_ActiveForm() )->SetStateVisible( true );
          }
          Update();

          return eEventReturnID::LastCall;
        }
      }
      //else
      //if( in_type_mouse_btn == WIN::Component::eMouseButton::Right )
      //{
      //  if( m_flag_expand == 0 )
      //  {
      //    // 子供メニューを表示
      //    CPL_SAFE_PTR( GetComponent_ActiveForm() )->SetStateVisible( true );
      //  }
      //  auto sp_comp_parent_menu = GetMenu_Parent();
      //  ActiveMenu* ptr_afm_form = dynamic_cast<ActiveMenu*>(&*sp_comp_parent_menu);
      //  if( ptr_afm_form )
      //  {
      //    // フォーム非表示
      //    ptr_afm_form->GetComponent_ActiveForm()->SetStateVisible( false );
      //  }
      //}
    }
  }

  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_MouseMove
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_MouseMove
    ( _in<sdptr<Component>> in_sp_component
    , _in<float           > in_mouse_x
    , _in<float           > in_mouse_y
    )
{
  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_Size
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_Size( _in<sdptr<Component>> in_sp_component )
{
  if( in_sp_component == this->GetLinkMyself() )
  {
    // 自身のサイズが変更された場合、保持するアイテムフォームの配置を修正する
    if( m_menu_ID != 0 ) // ポップアップルートでない場合
    {
      if( m_flag_expand == 1 ) // 展開されていたら
      {
        m_sp_item_container->SetSize
          ( float2( GetSize().x - 5, -1 )
          );
      }
    }
  }
  else
  if( in_sp_component == m_sp_item_container )
  {
    if( !(GetListMode() & eListMode::Fixed) )
    {
      size_t child_num = m_child_menu_table.size();
      auto item_form_size = m_sp_item_container->GetSize();

      //CPL_LOOP2( child_num, menu_idx )
      for( size_t menu_idx = 0; menu_idx < child_num; ++menu_idx )
      {
        // 横幅のみ変える
        m_child_menu_table[ menu_idx ]->
          SetSize( float2( item_form_size.x, -1 ) );
      }

      m_wp_active_form.lock()->AdjustSize();
    }
  }

  return eEventReturnID::SendParent_Position;
}



// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawBackground
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::On_DrawBackground( _in<float4> in_rect )
{
  auto ptr_color = &GetColorParameterBG()->color_default;
  auto ptr_active_comp = sm_sp_ac_comp().get();

  if( !this->IsEnable() )
  {
    ptr_color = &GetColorParameterBG()->color_invalid;
  }
  else
  {
    bool is_belong =
      ptr_active_comp
        ? ptr_active_comp->CheckBelongComponent( GetLinkMyself(), eParentType::Position )
        : false;
    if( ptr_active_comp == this  ||  is_belong )
    {
      ptr_color = &GetColorParameterBG()->color_highlight;
    }
  }

  //zzf_DrawRect_DefaultComponentBG( in_rect, sp_color->color );
  zzf_DrawRectEx( in_rect, ptr_color->color );
}



// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawFrame
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::On_DrawFrame( _in<float4> in_rect )
{
  //float4 color( m_sp_color_frame->sp_color_default );
  //if( !this->m_flag_enable )
  //{
  //  color = m_sp_color_frame->sp_color_invalid;
  //}
  //ef( this->sm_sp_ac_comp() == this  ||
  //    sm_sp_ac_comp()  &&  sm_sp_ac_comp()->CheckBelongComponent( getThisSmPtr() ) )
  //{
  //  color = m_sp_color_bg->sp_color_highlight;
  //}

  zzf_DrawFrame( in_rect, DX::ColorType{ 0.5f, 0.5f, 0.5f, 0.5f } );
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_DrawClient
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ActiveMenu::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) );
  
  auto ptr_active_comp   = SmartCast<Component*>(sm_sp_ac_comp());
  auto sp_colorset_text  = GetColorParameterText();
  auto sp_colorset_frame = GetColorParameterFrame();
  auto ptr_color_text    = &sp_colorset_text ->color_default;
  auto ptr_color_frame   = &sp_colorset_frame->color_default;

  if( !this->IsEnable() )
  {
    ptr_color_text  = &sp_colorset_text ->color_invalid;
    ptr_color_frame = &sp_colorset_frame->color_invalid;
  }
  else
  {
    bool is_belong =
      ptr_active_comp
        ? ptr_active_comp->CheckBelongComponent( GetLinkMyself(), eParentType::Position )
        : false;
    if( is_belong )
    {
      ptr_color_text  = &sp_colorset_text ->color_active;
      ptr_color_frame = &sp_colorset_frame->color_active;
    }
  }

  //
  float4 rt = in_rect;

  if( GetText().Comp( CPL_GUC_DEF_STR("-") ) == 0 )
  {
    float cy = rt.y + rt.Height() / 2;
    rt.y = cy - 1;
    rt.w = cy + 1;
    zzf_DrawFrameEx( rt, ptr_color_frame->color );
  }
  else
  if( GetText().Comp( CPL_GUC_DEF_STR("") ) ) // ""以外
  {
    rt.x += kSPACE + kSPACE_CHECK;
    rt.y += kSPACE;
    zzf_DrawText
      ( rt
      , GetText()
      , *ptr_color_text
      , 0.0f
      , float2( 0, 0 )
      , DX::kFDM_X_LEFT | DX::kFDM_Y_TOP
      );
  }

  //// シェーダー無効
  //ptr_d3d_dev->SetVertexShader( nullptr );
  //ptr_d3d_dev->SetPixelShader( nullptr );

  //
  //ptr_d3d_dev->SetFVF( DX::Vtx::XYZWC::FVF );
  //ptr_d3d_dev->SetTexture( 0, nullptr );

  // チェックマーク
  if( this->m_flag_check )
  {
    zzf_DrawParts
      ( float2(in_rect.x + kSPACE, in_rect.y + kSPACE)
      , eImagePartsID::Check
      , sp_colorset_text->color_default.color[0]
      );
  }

  // 子供がある場合は三角マークを表示（非固定モードの場合）
  if( this->m_child_menu_table.size() > 0  &&  !(GetListMode() & eListMode::Fixed) )
  {
    auto sp_menu_parent = GetMenu_Parent();
    ActiveMenu* ptr_menu_parent = dynamic_cast<ActiveMenu*>(&*sp_menu_parent);

    if( this->m_flag_expand  ||
        ptr_menu_parent  &&  ptr_menu_parent->GetListMode() & eListMode::AutoHorizontal )
    {
      zzf_DrawParts
        ( float2(in_rect.z-14, in_rect.y+4)
        , eImagePartsID::TriangleDown
        , kCOLOR_WHITE
        );
    }
    else
    {
      zzf_DrawParts
        ( float2(in_rect.z-14, in_rect.y+4)
        , eImagePartsID::TriangleRight
        , kCOLOR_WHITE 
        );
    }
  }
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::Component::On_UserProc
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_UserProc
    ( _in<sdptr<Component>> in_sp_component
    , _in<long            > in_message
    , _in<WPARAM          > in_wparam
    , _in<LPARAM          > in_lparam
    )
{
//  if( in_sp_component != this )
//  {
//    return false;
//  }

  switch( in_message )
  {
  case eID::ActiveViewItemShow:
    {
      sdptr<ActiveForm>
        sp_active_form =
          reinterpret_cast<ActiveForm*>(in_lparam)->GetLinkMyself<ActiveForm>();
      
      int level = FindActiveForm( sp_active_form.get() );
      if( level == 1 ) // 表示されたアクティブフォームが一つ下のクラスに属する場合
      {
        // 子供メニューから表示中のアクティブフォームがあれば非表示にする
        size_t child_num = m_child_menu_table.size();
        //CPL_LOOP2( child_num, menu_idx )
        for( size_t menu_idx = 0; menu_idx < child_num; ++menu_idx )
        {
          auto sp_menu_child = m_child_menu_table[ menu_idx ];

          if( sp_menu_child->GetComponent_ActiveForm() != sp_active_form  &&
              sp_menu_child->GetComponent_ActiveForm()->IsVisible() )
          {
            sp_menu_child->GetComponent_ActiveForm()->SetStateVisible( false );
            break;
          }
          sp_menu_child =
            std::dynamic_pointer_cast<GUC::ActiveMenu>(sp_menu_child->GetLinkNext());
        }
      }
      else
      {
        return eEventReturnID::SendParent_Position;
      }
    }
    SendParentMessage
      ( in_sp_component, in_message, in_wparam, in_lparam
      , eParentType::Position
      );
    break;

  case eID::ActiveViewItemHide:
    {
//      ActiveForm* ptr_ac_form = reinterpret_cast<ActiveForm*>(in_lparam);
//      if( ptr_ac_form )
//      {
//        ptr_ac_form->SetStateVisible( false );
//      }
      
      SendParentMessage
        ( in_sp_component, in_message, in_wparam, in_lparam
        , eParentType::Position
        );
    }
    break;

  case eID::ExpandMenu:
    AutoRepositionItems();
    break;
    
  default:
    return ActiveFormManager::On_UserProc( in_sp_component, in_message, in_wparam, in_lparam );
  }
  
  return eEventReturnID::LastCall;
}



// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseEnter
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_MouseEnter
    ( _in<sdptr<Component>> in_sp_comp_enter
    , _in<sdptr<Component>> in_sp_comp_leave
    )
{
  bool const is_self = in_sp_comp_enter == this->GetLinkMyself();

  if( is_self )
  {
    this->KillTimer( eID::Tid_MouseLeaveDelay );
    this->SetTimer( eID::Tid_MouseEnterDelay, 500 );

    // 説明
    if( m_explanation.Comp( CPL_GUC_DEF_STR("") ) )
    {
      SendMessage
        ( HWND_BROADCAST
        , eID::ChangeStatus
        , 0
        , reinterpret_cast<LPARAM>(&m_explanation[0])
        );
    }

    Update();
  }

  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::MouseEventInterface::On_MouseLeave
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_MouseLeave
    ( _in<sdptr<Component>> in_sp_comp_leave
    , _in<sdptr<Component>> in_sp_comp_enter
    )
{
  bool const is_self   = in_sp_comp_leave == this->GetLinkMyself();
  bool const is_belong = CheckBelongComponent( in_sp_comp_leave, eParentType::Position );

  // 自身もしくは属するコンポーネントの子供ならば
  if( is_self )
  {
    KillTimer( eID::Tid_MouseEnterDelay );
    SetTimer( eID::Tid_MouseLeaveDelay, 500 );
    Update();
  }
  if( is_self )
  {
    // 移動先のコンポーネントが自身の子供等ではない場合、非表示にする。
    if( !is_belong )
    {
      GetComponent_ActiveForm()->SetStateVisible( false );
    }
  }

  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::WindowEventInterface::On_Show
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID
  ActiveMenu::On_Show( _in<sdptr<Component>> in_sp_component, _in<BOOL> in_show_flag )
{
  if( m_flag_listmode & eListMode::Fixed )
  {
  }
  else
  {
    ActiveFormManager::On_Show( in_sp_component, in_show_flag );
  }

/*  if( show_flag )
  {
    SetUniqueActiveForm( m_sp_this );
  }
  else
  {
    SetUniqueActiveForm( nullptr );
  }*/

  return eEventReturnID::SendParent_Position;
}


// _____________________________________________________________________________
/// @copydoc CPL::GUC::WindowEventInterface::On_Timer
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
eEventReturnID ActiveMenu::On_Timer( _in<int> in_timer_ID )
{
  if( in_timer_ID == eID::Tid_MouseEnterDelay )
  {
    bool const is_child = this->m_child_menu_table.size() > 0;
    bool const is_popup = !this->m_flag_expand;
    // 子供メニューがあり、ポップアップ状態ならば。
    if( is_child  &&  is_popup )
    {
      auto sp_active_form = m_wp_active_form.lock();
      sp_active_form->SetStateVisible( true );
    }

    KillTimer( eID::Tid_MouseEnterDelay );
  }
  else
  if( in_timer_ID == eID::Tid_MouseLeaveDelay )
  {
    auto sp_active_form = m_wp_active_form.lock();
    auto sp_comp_over   = sm_sp_ac_comp(); // 
    if( sp_active_form  && sp_comp_over )
    {
      bool const is_exist_child = this->m_child_menu_table.size() > 0;
      bool const is_popup       = !this->m_flag_expand;
      bool const is_over_child  =
        sp_comp_over->CheckBelongComponent( sp_active_form, eParentType::Position );
      // 子供メニューがあり、ポップアップ状態ならば。
      if( is_exist_child  &&  is_popup  &&  !is_over_child )
      {
        sp_active_form->SetStateVisible( false );
      }

      KillTimer( eID::Tid_MouseLeaveDelay );
    }
  }

  return eEventReturnID::SendParent_Position;
}






//// _____________________________________________________________________________
///// @brief コンストラクタ
///// 
///// @param[in] in_sp_component_for_parent : 親コンポーネントのスマポ。
///// @param[in] in_pos_rect       : 表示矩形座標を格納したfloat4型へのポインタ。
///// @param[in] in_uv_rect        : 表示する対角UV座標を格納したfloat4型へのポインタ。
///// @param[in] in_cp_dib         : 適用するテクスチャのスマポ。
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//ActiveMenuImage::ActiveMenuImage
//( _in<sdptr<Component> > in_sp_component_for_parent
//, _in<float4           > in_pos_rect
//, _in<float4           > in_uv_rect
//, _in<DX::CpDXTexture2D> in_cp_dib
//) : ActiveMenu
//    ( in_sp_component_for_parent
//    , in_pos_rect
//    , CPL_GUC_DEF_STR("")
//    , -1
//    , eListMode::AutoVertical
//    , ActiveForm::ePosMode::BottomRightSide
//    )
//{
//  m_cp_dib = in_cp_dib;
//  m_dib_uv_rect = in_uv_rect;
//
//  zzf_SetInitializedLevel( zzf_GetClassLevel() );
//}
//
//
//// _____________________________________________________________________________
///// @brief メニューのアイテム描画（ActiveMenuImage拡張）
///// 
///// @param[in] in_mpos
///// 
///// @return 
//// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//void
//  ActiveMenuImage::DrawItem
//    ( _in<long2> in_mpos
//    , _in<int  > in_offs_x
//    , _in<int  > in_offs_y
//    )
//{
//  sm_def_sprite_mng().Draw
//    ( m_cp_dib
//    , in_mpos
//    , 
//      )
//}





} // namespace GUC
} // namespace CPL

