/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/11/16
/// 
/// @brief  Win32 コンテナ。
/// 
/// ※ 複数のコンポーネントを管理する。
/// 
/// ****************************************************************************

#pragma once

#include "CPL_WIN_Component.h"
#include "../../Base/CPL_WIN_DropFileControl.h"

namespace CPL {
namespace WIN {


class GroupBox;
class TabWindow;
class TextBox;
class ComboBox;
class ListBox;
class Button;
class ScrollBar;

// _____________________________________________________________________________
/// @brief コンテナクラス
///
// *****************************************************************************
class Container
  : public Component
{
private:
  struct ADJUST_ {
    int  size_x = 0;
    int  size_y = 0;
    HWND hdl_win_parent;
    BOOL view;
    ADJUST_( HWND in_hdl_window, BOOL in_flag_show )
      : hdl_win_parent( in_hdl_window )
      , view( in_flag_show )
    {}
  };
  static BOOL CALLBACK EnumChildProc_AdjustSize  ( HWND in_hdl_window, LPARAM in_lparam );
  static BOOL CALLBACK EnumChildProc_SetEnable   ( HWND in_hdl_window, LPARAM in_lparam );
  static BOOL CALLBACK EnumChildProc_SetEventMode( HWND in_hdl_window, LPARAM in_lparam );

//  U16  m_fEventEnableChild; // 子供からのメッセージ(WM_COMANND,WM_NOTIFY)を遮断するかどうか
                            // 0 : 遮断しない
                            // 1 : CPLのメッセージオーバライドは遮断するが、Win32のデフォルトプロシージャには処理を渡す
                            // 2 : 全て遮断

  /// メッセージを全て親に投げるかどうか。\n
  /// true:投げる。\n
  /// false:デフォルト処理を呼び出す。
  U32  m_flag_message_throw;

protected:
  // _____________________________________________________________________________
  /// @brief コンストラクタ（継承用）
  /// 
  /// @param[in] in_msg_throw
  ///   : true  - 自身のイベントメッセージを親にも転送する。\n
  ///   : false - 自身のイベントメッセージを親にも転送しない。
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  Container( bool in_msg_throw )
    : m_flag_message_throw( in_msg_throw )
  {};
  
  // _____________________________________________________________________________
  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  U32 zzf_GetMessageThrow() const { return m_flag_message_throw; }

  virtual SDEF  On_Command( _in<int > in_ctrl_ID
                          , _in<int > in_notify_code
                          , _in<HWND> in_hdl_ctrl_win
                          ){ return false; }
  virtual SDEF  On_Scroll        ( pio<ScrollBar> in_ptr_scroll, _in<int> in_flag_scroll ) { return false; }
  virtual SDEF  On_DropFile      ( DropFileControl& in_file_list     )                     { return false; }
  virtual SDEF  On_Notify        ( NMHDR*           in_ptr_nmhdr     )                     { return false; }
  virtual SDEF  On_TabChange     ( TabWindow*       in_ptr_tab_win   )                     { return false; }
  virtual SDEF  On_TextChange    ( TextBox*         in_ptr_text_box  )                     { return false; }
  virtual SDEF  On_ComboSelect   ( ComboBox*        in_ptr_combo_box )                     { return false; }
  virtual SDEF  On_ListSelect    ( ListBox*         in_ptr_list_box  )                     { return false; }
  virtual SDEF  On_Button        ( Button*          in_ptr_button, int in_flag_down )      { return false; }
  virtual SDEF  On_ExpandGroupBox( GroupBox*        in_ptr_group_box )                     { return false; }
  virtual SDEF  On_MenuSelect    ( HMENU in_hdl_menu, int in_menu_item, int in_menu_flags ){ return false; }

  virtual SDEF  DefaultProc_( _in<UINT> in_message, _in<WPARAM> in_wparam, _in<LPARAM> in_lparam ) override;
  
public:
  virtual td_Coord2 GetAdjustSize( _in<BOOL> in_flag_show ) const;
  virtual void      AdjustSize   ( _in<td_Coord2> in_offs_size = int2(0,0), _in<BOOL> in_flag_show = true );

  virtual void  SetEnable   ( _in<bool> in_flag_enable ) override;
  virtual void  SetEventMode( _in<eEventMode> in_event_mode ) override;

  Container
  ( _in<HWND     > in_hdl_win_parent
  , _in<td_Coord2> in_pos
  , _in<td_Coord2> in_size
  , _in<bool     > in_msg_throw = true
  );

  
  // _____________________________________________________________________________
  /// @brief コンテナクラス。Pimpl実装用
  ///
  // *****************************************************************************
  class Binder
    : public Component::Binder
  {
  private:
    auto getEntity()       { return dynamic_cast<Container*      >(&*impl); }
    auto getEntity() const { return dynamic_cast<Container const*>(&*impl); }
  public:
    td_Coord2 GetAdjustSize( _in<BOOL> in_flag_show )
    {
      return getEntity()->GetAdjustSize( in_flag_show );
    }
    void
      AdjustSize
        ( _in<td_Coord2> in_offs_size = td_Coord2(0,0)
        , _in<BOOL     > in_flag_show = true
        )
    {
      getEntity()->AdjustSize( in_offs_size, in_flag_show );
    }
    void SetEnable( _in<bool> in_enable )
    {
      getEntity()->SetEnable( in_enable );
    }
    void SetEventMode( _in<Component::eEventMode> in_event_mode )
    {
      getEntity()->SetEventMode ( in_event_mode );
    }

    Binder
    ( _in<HWND     > in_hdl_win_parent
    , _in<td_Coord2> in_pos
    , _in<td_Coord2> in_size
    , _in<bool     > in_msg_throw = true
    ) : Component::Binder
        ( CPL_NEW(Container)
          ( in_hdl_win_parent, in_pos, in_size, in_msg_throw ) )
    {}
  protected:
    // 継承用
    Binder( pio<Container> in_ptr_container )
      : Component::Binder( in_ptr_container )
    {}
    Binder( _in<sdptr<Container>> in_sp_container )
      : Component::Binder( in_sp_container )
    {}
  };
};




} // namespace WIN
} // namespace CPL
