/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/11/27
/// 
/// @brief  メニュー管理
/// 
/// ****************************************************************************

#pragma once

#include "../../../Core/CPL_Core.h"
#include "CPL_WIN_Component.h"


namespace CPL {
namespace WIN {


// _____________________________________________________________________________
/// @brief メニュークラス
///
// *****************************************************************************
class Menu
  : public Core::BaseObject
  , public Core::List::TreeElement< Menu, Core::List::DoublyElement<Menu> >
{
public:
  friend class Menu;
  friend CallPrivateConstructor<Menu>;
  friend class Core::List::DoublyElement<Menu>;
  friend class Core::List::TreeElement<Menu, Core::List::DoublyElement<Menu> >;

private:
  Menu
    ( pio<Menu    > in_ptr_menu_parent
    , pin<str_type> in_ptr_str
    , _in<int     > in_menu_ID
    , _in<int     > in_flag_popup = false
    );

  template<class T_STR>
  Menu
    ( pio<Menu > in_ptr_menu_parent
    , _in<T_STR> in_string
    , _in<int  > in_menu_ID
    , _in<int  > in_flag_popup = false
    ) : Menu( in_ptr_menu_parent, (str_cptr)in_string, in_menu_ID, in_flag_popup )
  {}

public:
  // _____________________________________________________________________________
  /// @brief メニュークラス　コンストラクタ
  /// 
  /// @param[in] in_ptr_str : 設定する文字列を指定します。
  /// @param[in] in_menu_ID : メニューのIDを指定します。
  /// @param[in] in_flag_popup
  ///   : true  - ポップアップまたは子供メニュー\n
  ///   : false - 固定メニュー
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Menu
  ( pin<str_type> in_ptr_str
  , _in<int     > in_menu_ID
  , _in<bool    > in_flag_popup = false
  ) : Menu( nullptr, in_ptr_str, in_menu_ID, in_flag_popup )
  {}

  template<class T_STR>
  Menu
  ( _in<T_STR> in_string
  , _in<int  > in_menu_ID
  , _in<bool > in_flag_popup = false
  ) : Menu( nullptr, &in_string[0], in_menu_ID, in_flag_popup )
  {}

  virtual ~Menu();

protected:
  int          m_index;
  MENUITEMINFO m_menu_info;
  HMENU        m_hdl_menu;     // メニューハンドル
  td_tstring   m_label_string;

//  void SetParam( MENUITEMINFO *menuInfo );
  bool zzf_SetState( DWORD in_flag, bool sw, int in_menu_ID = -1 );
  bool zzf_GetState( DWORD in_flag, int in_menu_ID = -1 ) const;

private:
  Menu const* zzf_getItem_Idx_( int in_index ) const;
  Menu const* zzf_getItem_ID_( int in_menu_ID ) const;
public:
  HMENU       GetHandle() const { return m_hdl_menu; }
  auto&       GetString()       { return m_label_string; }
  auto const& GetString() const { return m_label_string; }

  Menu const*
    GetItem_Idx( _in<int> in_index ) const
  {
      return zzf_getItem_Idx_( in_index );
  }
  Menu*
    GetItem_Idx( _in<int> in_index )
  {
    return const_cast<Menu*>( zzf_getItem_Idx_( in_index ) );
  }
  Menu const*
    GetItem_ID( _in<int> in_menu_ID ) const
  {
    return zzf_getItem_ID_( in_menu_ID );
  }
  Menu*
    GetItem_ID( _in<int> in_menu_ID )
  {
    return const_cast<Menu*>( zzf_getItem_ID_( in_menu_ID ) );
  }
  int   GetID()  const { return m_menu_info.wID; }
  int   GetIdx() const { return m_index; }
  Menu* InsertItem
          ( _in<str_cptr> in_ptr_str
          , _in<int     > in_menu_ID
          , _in<int     > in_index = -1
          );
  Menu* InsertItem
          ( pio<Menu> in_ptr_menu
          , _in<int > in_index
          );
  bool  ChangeItem( _in<Core::String> in_string, _in<int> in_menu_ID );
//  int   Remove( int in_index );
  void  DeleteItem( _in<int> in_index );
  bool  Set( _in<HWND> in_hdl_window );
  bool  SetCheck( _in<BOOL> in_flag_check, _in<int> in_menu_ID = -1 );
  bool  GetCheck( _in<int> in_menu_ID = -1 ) const;
  bool  SetGray( _in<bool> in_flag_gray, _in<int> in_menu_ID = -1 );
  bool  GetGray( _in<int> in_menu_ID = -1 ) const;
};




} // namespace WIN
} // namespace CPL
