/// ****************************************************************************
/// @file   
/// @author Dr.Neeton
/// @date   200X/X/X - 2016/11/11
/// 
/// @brief  Win32 イメージウィンドウ周り。
/// 
/// ****************************************************************************

#pragma once

#include "../Frame/CPL_WIN_Window.h"
#include "CPL_WIN_Scrollbar.h"
#include "../../GObj/CPL_WIN_Graphics.h"
#include "../../GObj/CPL_WIN_DIBitmap.h"


namespace CPL {
namespace WIN {



// _____________________________________________________________________________
/// @brief イメージボックス
/// 
/// ※ 継承する場合は、描画に On_Paint ではなく On_Draw*** を使用
///
// *****************************************************************************
class ImageBox
  : public Component
{
private:
  SDEF On_Paint();
  SDEF DefaultProc_( _in<UINT> msg, _in<WPARAM> wp, _in<LPARAM> lp );

protected:
  HDC         m_hdl_DC;       /// 関連付けられたウィンドウのデバイスコンテキストを保持。
  PAINTSTRUCT m_PS;           /// PAINTSTRUCT構造体。
  COLORREF    m_back_color;   /// イメージ用背景色
  td_Coord2   m_canval_size;  /// キャンバスサイズ。
  td_Coord2   m_canvas_top;   /// 描画座標のオフセット。
  float       m_canvas_scale; /// 描画倍率。
  float       m_alpha;        /// 描画透過率。

  HdcSurface* m_ptr_back_surface; /// バックバッファ用サーフェイス。
  HdcBitmap*  m_ptr_back_bmp;

  void zzf_AdjustScrollBar();

  SDEF On_Size( _in<eSizeMode> in_size_mode );
  virtual SDEF On_DrawCanvas( HDC in_hdc ){ return false; }
  virtual SDEF On_DrawFront( HDC in_hdc ){ return false; }

public:
  void CallPaint(){ On_Paint(); } // On_Paint()強制呼び出し

  virtual void  Start();
  virtual void  Clear();
  virtual void  Renew();
  virtual void  End  ();

  virtual void      DrawLine      ( _in<td_Coord2> in_start, _in<td_Coord2> in_end ){ m_ptr_back_surface->DrawLine( in_start, in_end );         }
  virtual void      DrawLineTo    ( _in<td_Coord2> in_end )                         { m_ptr_back_surface->DrawLineTo( in_end );                 }
  virtual void      DrawFillBox   ( _in<Rect> in_rect, HBRUSH in_hdl_brush ){ m_ptr_back_surface->DrawFillBox( in_rect, in_hdl_brush ); }
  virtual void      DrawFrameBox  ( _in<Rect> in_rect )                     { m_ptr_back_surface->DrawFrameBox( in_rect );              }
  virtual void      DrawImage     ( pin<DIBitmap> in_ptr_image );
  virtual void      SetCanvasSize ( _in<td_Coord2> in_size );
  virtual void      SetCanvasScale( _in<float> in_scale );
  virtual void      SetDrawAlpha  ( _in<float> in_alpha )                  { m_alpha = in_alpha;                 }
  virtual HDC       GetDC         ()                            const { return m_ptr_back_surface->GetDC(); }
  virtual void      GetScrollInfoH( SCROLLINFO* in_ptr_scinfo ) const;
  virtual void      GetScrollInfoV( SCROLLINFO* in_ptr_scinfo ) const;
  virtual td_Coord2 GetCanvasSize ()                            const { return m_canval_size;  }
  virtual float     GetCanvasScale()                            const { return m_canvas_scale; }
  virtual float     GetDrawAlpha  ()                            const { return m_alpha;        }


  ImageBox
  ( _in<HWND     > in_hdl_win_parent
  , _in<td_Coord2> in_pos
  , _in<td_Coord2> in_size
  , _in<COLORREF > in_back_color = RGB(0,0,0)
  , _in<bool     > in_flag_client_size = true
  );

  virtual ~ImageBox();
  

  // _____________________________________________________________________________
  /// @brief イメージボックス　Pimpl実装用
  ///
  // *****************************************************************************
  class Binder
    : public Component::Binder
  {
  private:
    ImageBox*       getEntity()       { return dynamic_cast<ImageBox*      >(&*impl); }
    ImageBox const* getEntity() const { return dynamic_cast<ImageBox const*>(&*impl); }

  public:
    void   CallPaint()
    {
      getEntity()->CallPaint();
    } // On_Paint()強制呼び出し

    void  Start(){ getEntity()->Start(); }
    void  Clear(){ getEntity()->Clear(); }
    void  Renew(){ getEntity()->Renew(); }
    void  End  (){ getEntity()->End(); }

    void  DrawLine      ( _in<td_Coord2> in_start_pos, _in<td_Coord2> in_end_pos ){  getEntity()->DrawLine      ( in_start_pos, in_end_pos );     }
    void  DrawLineTo    ( _in<td_Coord2> in_end_pos )                             {  getEntity()->DrawLineTo    ( in_end_pos );            }
    void  DrawFillBox   ( _in<Rect> in_rect, HBRUSH in_hdl_brush ){        getEntity()->DrawFillBox   ( in_rect, in_hdl_brush );     }
    void  DrawFrameBox  ( _in<Rect> in_rect )                     {        getEntity()->DrawFrameBox  ( in_rect );             }
    void  DrawImage     ( pin<DIBitmap> in_ptr_image )            {        getEntity()->DrawImage     ( in_ptr_image );          }
    void  SetCanvasSize ( _in<td_Coord2> in_size )                {        getEntity()->SetCanvasSize ( in_size );           }
    void  SetCanvasScale( _in<float> in_scale )                   {        getEntity()->SetCanvasScale( in_scale );          }
    void  SetDrawAlpha  ( _in<float> in_alpha )                   {        getEntity()->SetDrawAlpha  ( in_alpha );          }
    HDC   GetDC         ()                                  const { return getEntity()->GetDC         ();                 }
    void  GetScrollInfoH( SCROLLINFO* in_ptr_scroll_info )  const {        getEntity()->GetScrollInfoH( in_ptr_scroll_info );           }
    void  GetScrollInfoV( SCROLLINFO* in_ptr_scroll_info )  const {        getEntity()->GetScrollInfoV( in_ptr_scroll_info );           }
    auto  GetCanvasSize ()                                  const { return getEntity()->GetCanvasSize ();                 }
    float GetCanvasScale()                                  const { return getEntity()->GetCanvasScale();                 }
    float GetDrawAlpha  ()                                  const { return getEntity()->GetDrawAlpha  ();                 }


    Binder
    ( _in<HWND     > in_hdl_win_parent
    , _in<td_Coord2> in_pos
    , _in<td_Coord2> in_size
    , _in<COLORREF > in_back_color = RGB(0,0,0)
    , _in<bool     > in_flag_client_size = true
    ) : Component::Binder
        ( CPL_NEW(ImageBox)
            ( in_hdl_win_parent
            , in_pos
            , in_size
            , in_back_color
            , in_flag_client_size
            )
        )
    {}
  protected:
    // 継承用
    Binder( ImageBox* in_ptr_image_box )
      : Component::Binder( in_ptr_image_box )
    {}
  };

};


} // namespace WIN
} // namespace CPL
