// Copyright 2014 PDFium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com

#ifndef XFA_FWL_CORE_FWL_WIDGETIMP_H_
#define XFA_FWL_CORE_FWL_WIDGETIMP_H_

#include "core/fxcrt/include/fx_coordinates.h"
#include "core/fxcrt/include/fx_system.h"
#include "xfa/fwl/core/cfwl_event.h"
#include "xfa/fwl/core/fwl_targetimp.h"
#include "xfa/fwl/core/ifwl_widgetdelegate.h"

class CFWL_MsgKey;
class CFWL_ThreadImp;
class CFWL_WidgetImpProperties;
class CFWL_WidgetMgr;
class IFWL_DataProvider;
class IFWL_Thread;
class IFWL_ThemeProvider;
class IFWL_Widget;

class CFWL_WidgetImp : public CFWL_TargetImp {
 public:
  virtual FWL_ERR Initialize();
  virtual FWL_ERR Finalize();

  virtual FWL_ERR GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize = FALSE);
  virtual FWL_ERR GetGlobalRect(CFX_RectF& rect);
  virtual FWL_ERR SetWidgetRect(const CFX_RectF& rect);
  virtual FWL_ERR GetClientRect(CFX_RectF& rect);
  virtual IFWL_Widget* GetParent();
  virtual FWL_ERR SetParent(IFWL_Widget* pParent);
  virtual IFWL_Widget* GetOwner();
  virtual FWL_ERR SetOwner(IFWL_Widget* pOwner);
  virtual IFWL_Widget* GetOuter();
  virtual uint32_t GetStyles();
  virtual FWL_ERR ModifyStyles(uint32_t dwStylesAdded,
                               uint32_t dwStylesRemoved);
  virtual uint32_t GetStylesEx();
  virtual FWL_ERR ModifyStylesEx(uint32_t dwStylesExAdded,
                                 uint32_t dwStylesExRemoved);
  virtual uint32_t GetStates();
  virtual FWL_ERR SetStates(uint32_t dwStates, FX_BOOL bSet = TRUE);
  virtual FWL_ERR SetPrivateData(void* module_id,
                                 void* pData,
                                 PD_CALLBACK_FREEDATA callback);
  virtual void* GetPrivateData(void* module_id);
  virtual FWL_ERR Update();
  virtual FWL_ERR LockUpdate();
  virtual FWL_ERR UnlockUpdate();
  virtual uint32_t HitTest(FX_FLOAT fx, FX_FLOAT fy);
  virtual FWL_ERR TransformTo(IFWL_Widget* pWidget, FX_FLOAT& fx, FX_FLOAT& fy);
  virtual FWL_ERR TransformTo(IFWL_Widget* pWidget, CFX_RectF& rt);
  virtual FWL_ERR GetMatrix(CFX_Matrix& matrix, FX_BOOL bGlobal = FALSE);
  virtual FWL_ERR SetMatrix(const CFX_Matrix& matrix);
  virtual FWL_ERR DrawWidget(CFX_Graphics* pGraphics,
                             const CFX_Matrix* pMatrix = NULL);
  virtual IFWL_ThemeProvider* GetThemeProvider();
  virtual FWL_ERR SetThemeProvider(IFWL_ThemeProvider* pThemeProvider);
  virtual FWL_ERR SetDataProvider(IFWL_DataProvider* pDataProvider);
  virtual IFWL_WidgetDelegate* SetDelegate(IFWL_WidgetDelegate* pDelegate);
  virtual IFWL_Thread* GetOwnerThread() const;
  FWL_ERR SetOwnerThread(CFWL_ThreadImp* pOwnerThread);
  IFWL_Widget* GetInterface() const;
  void SetInterface(IFWL_Widget* pInterface);
  CFX_SizeF GetOffsetFromParent(IFWL_Widget* pParent);

 protected:
  CFWL_WidgetImp(const CFWL_WidgetImpProperties& properties,
                 IFWL_Widget* pOuter);
  virtual ~CFWL_WidgetImp();
  FX_BOOL IsEnabled() const;
  FX_BOOL IsVisible() const;
  FX_BOOL IsActive() const;
  FX_BOOL IsOverLapper() const;
  FX_BOOL IsPopup() const;
  FX_BOOL IsChild() const;
  FX_BOOL IsLocked() const;
  FX_BOOL IsOffscreen() const;
  FX_BOOL HasBorder() const;
  FX_BOOL HasEdge() const;
  void GetEdgeRect(CFX_RectF& rtEdge);
  FX_FLOAT GetBorderSize(FX_BOOL bCX = TRUE);
  FX_FLOAT GetEdgeWidth();
  void GetRelativeRect(CFX_RectF& rect);
  void* GetThemeCapacity(uint32_t dwCapacity);
  IFWL_ThemeProvider* GetAvailableTheme();
  CFWL_WidgetImp* GetRootOuter();
  CFX_SizeF CalcTextSize(const CFX_WideString& wsText,
                         IFWL_ThemeProvider* pTheme,
                         FX_BOOL bMultiLine = FALSE,
                         int32_t iLineWidth = -1);
  void CalcTextRect(const CFX_WideString& wsText,
                    IFWL_ThemeProvider* pTheme,
                    uint32_t dwTTOStyles,
                    int32_t iTTOAlign,
                    CFX_RectF& rect);
  void SetFocus(FX_BOOL bFocus);
  void SetGrab(FX_BOOL bSet);
  FX_BOOL GetPopupPos(FX_FLOAT fMinHeight,
                      FX_FLOAT fMaxHeight,
                      const CFX_RectF& rtAnchor,
                      CFX_RectF& rtPopup);
  FX_BOOL GetPopupPosMenu(FX_FLOAT fMinHeight,
                          FX_FLOAT fMaxHeight,
                          const CFX_RectF& rtAnchor,
                          CFX_RectF& rtPopup);
  FX_BOOL GetPopupPosComboBox(FX_FLOAT fMinHeight,
                              FX_FLOAT fMaxHeight,
                              const CFX_RectF& rtAnchor,
                              CFX_RectF& rtPopup);
  FX_BOOL GetPopupPosGeneral(FX_FLOAT fMinHeight,
                             FX_FLOAT fMaxHeight,
                             const CFX_RectF& rtAnchor,
                             CFX_RectF& rtPopup);
  FX_BOOL GetScreenSize(FX_FLOAT& fx, FX_FLOAT& fy);
  void RegisterEventTarget(IFWL_Widget* pEventSource = NULL,
                           uint32_t dwFilter = FWL_EVENT_ALL_MASK);
  void UnregisterEventTarget();
  void DispatchKeyEvent(CFWL_MsgKey* pNote);
  void DispatchEvent(CFWL_Event* pEvent);
  void Repaint(const CFX_RectF* pRect = NULL);
  void DrawBackground(CFX_Graphics* pGraphics,
                      int32_t iPartBk,
                      IFWL_ThemeProvider* pTheme,
                      const CFX_Matrix* pMatrix = NULL);
  void DrawBorder(CFX_Graphics* pGraphics,
                  int32_t iPartBorder,
                  IFWL_ThemeProvider* pTheme,
                  const CFX_Matrix* pMatrix = NULL);
  void DrawEdge(CFX_Graphics* pGraphics,
                int32_t iPartEdge,
                IFWL_ThemeProvider* pTheme,
                const CFX_Matrix* pMatrix = NULL);
  void NotifyDriver();

  FX_BOOL IsParent(IFWL_Widget* pParent);

  friend class CFWL_WidgetImpDelegate;

  CFWL_WidgetMgr* m_pWidgetMgr;
  CFWL_ThreadImp* m_pOwnerThread;
  CFWL_WidgetImpProperties* m_pProperties;
  CFX_PrivateData* m_pPrivateData;
  IFWL_WidgetDelegate* m_pDelegate;
  IFWL_WidgetDelegate* m_pCurDelegate;
  IFWL_Widget* m_pOuter;
  IFWL_Widget* m_pInterface;
  int32_t m_iLock;
};

class CFWL_WidgetImpDelegate : public IFWL_WidgetDelegate {
 public:
  CFWL_WidgetImpDelegate();
  ~CFWL_WidgetImpDelegate() override {}
  int32_t OnProcessMessage(CFWL_Message* pMessage) override;
  FWL_ERR OnProcessEvent(CFWL_Event* pEvent) override;
  FWL_ERR OnDrawWidget(CFX_Graphics* pGraphics,
                       const CFX_Matrix* pMatrix = NULL) override;
};

#endif  // XFA_FWL_CORE_FWL_WIDGETIMP_H_
