// 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

#include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h"

#include "xfa/include/fwl/core/fwl_theme.h"
#include "xfa/src/fdp/include/fde_tto.h"
#include "xfa/src/fwl/src/basewidget/include/fwl_editimp.h"
#include "xfa/src/fwl/src/basewidget/include/fwl_formproxyimp.h"
#include "xfa/src/fwl/src/basewidget/include/fwl_listboximp.h"
#include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h"
#include "xfa/src/fwl/src/core/include/fwl_appimp.h"
#include "xfa/src/fwl/src/core/include/fwl_formimp.h"
#include "xfa/src/fwl/src/core/include/fwl_noteimp.h"
#include "xfa/src/fwl/src/core/include/fwl_panelimp.h"
#include "xfa/src/fwl/src/core/include/fwl_targetimp.h"
#include "xfa/src/fwl/src/core/include/fwl_threadimp.h"
#include "xfa/src/fwl/src/core/include/fwl_widgetimp.h"
#include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h"

// static
IFWL_ComboBox* IFWL_ComboBox::Create(
    const CFWL_WidgetImpProperties& properties) {
  IFWL_ComboBox* pComboBox = new IFWL_ComboBox;
  CFWL_ComboBoxImp* pComboBoxImpl = new CFWL_ComboBoxImp(properties, nullptr);
  pComboBox->SetImpl(pComboBoxImpl);
  pComboBoxImpl->SetInterface(pComboBox);
  return pComboBox;
}
IFWL_ComboBox::IFWL_ComboBox() {}
int32_t IFWL_ComboBox::GetCurSel() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetCurSel();
}
FWL_ERR IFWL_ComboBox::SetCurSel(int32_t iSel) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetCurSel(iSel);
}
FWL_ERR IFWL_ComboBox::SetEditText(const CFX_WideString& wsText) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditText(wsText);
}
int32_t IFWL_ComboBox::GetEditTextLength() const {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditTextLength();
}
FWL_ERR IFWL_ComboBox::GetEditText(CFX_WideString& wsText,
                                   int32_t nStart,
                                   int32_t nCount) const {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())
      ->GetEditText(wsText, nStart, nCount);
}
FWL_ERR IFWL_ComboBox::SetEditSelRange(int32_t nStart, int32_t nCount) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())
      ->SetEditSelRange(nStart, nCount);
}
int32_t IFWL_ComboBox::GetEditSelRange(int32_t nIndex, int32_t& nStart) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())
      ->GetEditSelRange(nIndex, nStart);
}
int32_t IFWL_ComboBox::GetEditLimit() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditLimit();
}
FWL_ERR IFWL_ComboBox::SetEditLimit(int32_t nLimit) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditLimit(nLimit);
}
FWL_ERR IFWL_ComboBox::EditDoClipboard(int32_t iCmd) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDoClipboard(iCmd);
}
FX_BOOL IFWL_ComboBox::EditRedo(const CFX_ByteStringC& bsRecord) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(bsRecord);
}
FX_BOOL IFWL_ComboBox::EditUndo(const CFX_ByteStringC& bsRecord) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(bsRecord);
}
IFWL_ListBox* IFWL_ComboBox::GetListBoxt() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetListBoxt();
}
FX_BOOL IFWL_ComboBox::AfterFocusShowDropList() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->AfterFocusShowDropList();
}
FX_ERR IFWL_ComboBox::OpenDropDownList(FX_BOOL bActivate) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->OpenDropDownList(bActivate);
}
FX_BOOL IFWL_ComboBox::EditCanUndo() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanUndo();
}
FX_BOOL IFWL_ComboBox::EditCanRedo() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanRedo();
}
FX_BOOL IFWL_ComboBox::EditUndo() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo();
}
FX_BOOL IFWL_ComboBox::EditRedo() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo();
}
FX_BOOL IFWL_ComboBox::EditCanCopy() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCopy();
}
FX_BOOL IFWL_ComboBox::EditCanCut() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCut();
}
FX_BOOL IFWL_ComboBox::EditCanSelectAll() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanSelectAll();
}
FX_BOOL IFWL_ComboBox::EditCopy(CFX_WideString& wsCopy) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCopy(wsCopy);
}
FX_BOOL IFWL_ComboBox::EditCut(CFX_WideString& wsCut) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCut(wsCut);
}
FX_BOOL IFWL_ComboBox::EditPaste(const CFX_WideString& wsPaste) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditPaste(wsPaste);
}
FX_BOOL IFWL_ComboBox::EditSelectAll() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditSelectAll();
}
FX_BOOL IFWL_ComboBox::EditDelete() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDelete();
}
FX_BOOL IFWL_ComboBox::EditDeSelect() {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDeSelect();
}
FWL_ERR IFWL_ComboBox::GetBBox(CFX_RectF& rect) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetBBox(rect);
}
FWL_ERR IFWL_ComboBox::EditModifyStylesEx(FX_DWORD dwStylesExAdded,
                                          FX_DWORD dwStylesExRemoved) {
  return static_cast<CFWL_ComboBoxImp*>(GetImpl())
      ->EditModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
}

CFWL_ComboEditImp::CFWL_ComboEditImp(const CFWL_WidgetImpProperties& properties,
                                     IFWL_Widget* pOuter)
    : CFWL_EditImp(properties, pOuter) {
  m_pOuter = static_cast<CFWL_ComboBoxImp*>(pOuter->GetImpl());
}

CFWL_ComboEditImpDelegate::CFWL_ComboEditImpDelegate(CFWL_ComboEditImp* pOwner)
    : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) {
}
int32_t CFWL_ComboEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
  if (!pMessage)
    return 0;
  FX_DWORD dwMsgCode = pMessage->GetClassID();
  FX_BOOL backDefault = TRUE;
  switch (dwMsgCode) {
    case FWL_MSGHASH_SetFocus:
    case FWL_MSGHASH_KillFocus: {
      if (dwMsgCode == FWL_MSGHASH_SetFocus) {
        m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
      } else {
        m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
      }
      backDefault = FALSE;
      break;
    }
    case FWL_MSGHASH_Mouse: {
      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
      if ((pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) &&
          ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)) {
        m_pOwner->SetSelected();
        m_pOwner->SetComboBoxFocus(TRUE);
      }
      break;
    }
    default: {}
  }
  if (!backDefault) {
    return 1;
  }
  return CFWL_EditImpDelegate::OnProcessMessage(pMessage);
}
void CFWL_ComboEditImp::ClearSelected() {
  ClearSelections();
  Repaint(&m_rtClient);
}
void CFWL_ComboEditImp::SetSelected() {
  FlagFocus(TRUE);
  EndCaret();
  AddSelRange(0);
}
void CFWL_ComboEditImp::EndCaret() {
  m_pEdtEngine->MoveCaretPos(MC_End);
}
void CFWL_ComboEditImp::FlagFocus(FX_BOOL bSet) {
  if (bSet) {
    m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
  } else {
    m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    ShowCaret(FALSE);
  }
}
void CFWL_ComboEditImp::SetComboBoxFocus(FX_BOOL bSet) {
  m_pOuter->SetFocus(bSet);
}
CFWL_ComboListImp::CFWL_ComboListImp(const CFWL_WidgetImpProperties& properties,
                                     IFWL_Widget* pOuter)
    : CFWL_ListBoxImp(properties, pOuter), m_bNotifyOwner(TRUE) {
  FXSYS_assert(pOuter != NULL);
}
FWL_ERR CFWL_ComboListImp::Initialize() {
  if (CFWL_ListBoxImp::Initialize() != FWL_ERR_Succeeded)
    return FWL_ERR_Indefinite;
  delete m_pDelegate;
  m_pDelegate = new CFWL_ComboListImpDelegate(this);
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboListImp::Finalize() {
  delete m_pDelegate;
  m_pDelegate = nullptr;
  return CFWL_ListBoxImp::Finalize();
}
int32_t CFWL_ComboListImp::MatchItem(const CFX_WideString& wsMatch) {
  if (wsMatch.IsEmpty()) {
    return -1;
  }
  if (!m_pProperties->m_pDataProvider)
    return -1;
  IFWL_ListBoxDP* pData =
      static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
  int32_t iCount = pData->CountItems(m_pInterface);
  for (int32_t i = 0; i < iCount; i++) {
    FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i);
    CFX_WideString wsText;
    pData->GetItemText(m_pInterface, hItem, wsText);
    FX_STRSIZE pos = wsText.Find(wsMatch.c_str());
    if (!pos) {
      return i;
    }
  }
  return -1;
}
void CFWL_ComboListImp::ChangeSelected(int32_t iSel) {
  if (!m_pProperties->m_pDataProvider)
    return;
  IFWL_ListBoxDP* pData =
      static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
  FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);
  CFX_RectF rtInvalidate;
  rtInvalidate.Reset();
  FWL_HLISTITEM hOld = GetSelItem(0);
  int32_t iOld = pData->GetItemIndex(m_pInterface, hOld);
  if (iOld == iSel) {
    return;
  } else if (iOld > -1) {
    GetItemRect(iOld, rtInvalidate);
    SetSelItem(hOld, FALSE);
  }
  if (hItem) {
    CFX_RectF rect;
    GetItemRect(iSel, rect);
    rtInvalidate.Union(rect);
    FWL_HLISTITEM hSel = pData->GetItem(m_pInterface, iSel);
    SetSelItem(hSel, TRUE);
  }
  if (!rtInvalidate.IsEmpty()) {
    Repaint(&rtInvalidate);
  }
}
int32_t CFWL_ComboListImp::CountItems() {
  IFWL_ListBoxDP* pData =
      static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
  return pData ? pData->CountItems(m_pInterface) : 0;
}
void CFWL_ComboListImp::GetItemRect(int32_t nIndex, CFX_RectF& rtItem) {
  IFWL_ListBoxDP* pData =
      static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider);
  FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, nIndex);
  pData->GetItemRect(m_pInterface, hItem, rtItem);
}
void CFWL_ComboListImp::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) {
  fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top;
  IFWL_Widget* pOwner = GetOwner();
  if (!pOwner)
    return;
  pOwner->TransformTo(m_pOuter, fx, fy);
}
void CFWL_ComboListImp::SetFocus(FX_BOOL bSet) {
  CFWL_WidgetImp::SetFocus(bSet);
}
CFWL_ComboListImpDelegate::CFWL_ComboListImpDelegate(CFWL_ComboListImp* pOwner)
    : CFWL_ListBoxImpDelegate(pOwner), m_pOwner(pOwner) {
}
int32_t CFWL_ComboListImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
  if (!pMessage)
    return 0;
  FX_DWORD dwHashCode = pMessage->GetClassID();
  FX_BOOL backDefault = TRUE;
  if (dwHashCode == FWL_MSGHASH_SetFocus ||
      dwHashCode == FWL_MSGHASH_KillFocus) {
    OnDropListFocusChanged(pMessage, dwHashCode == FWL_MSGHASH_SetFocus);
  } else if (dwHashCode == FWL_MSGHASH_Mouse) {
    CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
    if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
      CFX_RectF rect;
      m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
      if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
        pMsg->m_fx -= rect.left;
        pMsg->m_fy -= rect.top;
        IFWL_WidgetDelegate* pDelegate =
            m_pOwner->m_pVertScrollBar->SetDelegate(NULL);
        return pDelegate->OnProcessMessage(pMsg);
      }
    }
    FX_DWORD dwCmd = pMsg->m_dwCmd;
    switch (dwCmd) {
      case FWL_MSGMOUSECMD_MouseMove: {
        backDefault = FALSE;
        OnDropListMouseMove(pMsg);
        break;
      }
      case FWL_MSGMOUSECMD_LButtonDown: {
        backDefault = FALSE;
        OnDropListLButtonDown(pMsg);
        break;
      }
      case FWL_MSGMOUSECMD_LButtonUp: {
        backDefault = FALSE;
        OnDropListLButtonUp(pMsg);
        break;
      }
      default: {}
    }
  } else if (dwHashCode == FWL_MSGHASH_Key) {
    backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage));
  }
  if (!backDefault) {
    return 1;
  }
  return CFWL_ListBoxImpDelegate::OnProcessMessage(pMessage);
}
void CFWL_ComboListImpDelegate::OnDropListFocusChanged(CFWL_Message* pMsg,
                                                       FX_BOOL bSet) {
  if (!bSet) {
    CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg);
    CFWL_ComboBoxImp* pOuter =
        static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    if (pKill->m_pSetFocus == m_pOwner->m_pOuter ||
        pKill->m_pSetFocus == pOuter->m_pEdit.get()) {
      pOuter->ShowDropList(FALSE);
    }
  }
}
int32_t CFWL_ComboListImpDelegate::OnDropListMouseMove(CFWL_MsgMouse* pMsg) {
  if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    if (m_pOwner->m_bNotifyOwner) {
      m_pOwner->m_bNotifyOwner = FALSE;
    }
    if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
      CFX_RectF rect;
      m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
      if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
        return 1;
      }
    }
    FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
    if (hItem) {
      if (!m_pOwner->m_pProperties->m_pDataProvider)
        return 0;
      IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
          m_pOwner->m_pProperties->m_pDataProvider);
      int32_t iSel = pData->GetItemIndex(m_pOwner->m_pInterface, hItem);
      CFWL_EvtCmbHoverChanged event;
      event.m_pSrcTarget = m_pOwner->m_pOuter;
      event.m_iCurHover = iSel;
      m_pOwner->DispatchEvent(&event);
      m_pOwner->ChangeSelected(iSel);
    }
  } else if (m_pOwner->m_bNotifyOwner) {
    m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);
    CFWL_ComboBoxImp* pOuter =
        static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
    pOuter->m_pDelegate->OnProcessMessage(pMsg);
  }
  return 1;
}
int32_t CFWL_ComboListImpDelegate::OnDropListLButtonDown(CFWL_MsgMouse* pMsg) {
  if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) {
    return 0;
  }
  CFWL_ComboBoxImp* pOuter =
      static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
  pOuter->ShowDropList(FALSE);
  return 1;
}
int32_t CFWL_ComboListImpDelegate::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) {
  CFWL_ComboBoxImp* pOuter =
      static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
  if (m_pOwner->m_bNotifyOwner) {
    m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy);
    pOuter->m_pDelegate->OnProcessMessage(pMsg);
  } else {
    if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) {
      CFX_RectF rect;
      m_pOwner->m_pVertScrollBar->GetWidgetRect(rect);
      if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) {
        return 1;
      }
    }
    pOuter->ShowDropList(FALSE);
    FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy);
    if (hItem) {
      pOuter->ProcessSelChanged(TRUE);
    }
  }
  return 1;
}
int32_t CFWL_ComboListImpDelegate::OnDropListKey(CFWL_MsgKey* pKey) {
  CFWL_ComboBoxImp* pOuter =
      static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
  FX_BOOL bPropagate = FALSE;
  if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {
    FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
    switch (dwKeyCode) {
      case FWL_VKEY_Return:
      case FWL_VKEY_Escape: {
        pOuter->ShowDropList(FALSE);
        return 1;
      }
      case FWL_VKEY_Up:
      case FWL_VKEY_Down: {
        OnDropListKeyDown(pKey);
        pOuter->SetDelegate(nullptr);
        pOuter->ProcessSelChanged(FALSE);
        return 1;
      }
      default: { bPropagate = TRUE; }
    }
  } else if (pKey->m_dwCmd == FWL_MSGKEYCMD_Char) {
    bPropagate = TRUE;
  }
  if (bPropagate) {
    pKey->m_pDstTarget = m_pOwner->m_pOuter;
    pOuter->m_pDelegate->OnProcessMessage(pKey);
    return 1;
  }
  return 0;
}
void CFWL_ComboListImpDelegate::OnDropListKeyDown(CFWL_MsgKey* pKey) {
  FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
  switch (dwKeyCode) {
    case FWL_VKEY_Up:
    case FWL_VKEY_Down:
    case FWL_VKEY_Home:
    case FWL_VKEY_End: {
      CFWL_ComboBoxImp* pOuter =
          static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl());
      IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
          m_pOwner->m_pProperties->m_pDataProvider);
      FWL_HLISTITEM hItem =
          pData->GetItem(m_pOwner->m_pInterface, pOuter->m_iCurSel);
      hItem = m_pOwner->GetItem(hItem, dwKeyCode);
      if (!hItem) {
        break;
      }
      m_pOwner->SetSelection(hItem, hItem, TRUE);
      m_pOwner->ScrollToVisible(hItem);
      CFX_RectF rtInvalidate;
      rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width,
                       m_pOwner->m_pProperties->m_rtWidget.height);
      m_pOwner->Repaint(&rtInvalidate);
      break;
    }
    default: {}
  }
}
CFWL_ComboBoxImp::CFWL_ComboBoxImp(const CFWL_WidgetImpProperties& properties,
                                   IFWL_Widget* pOuter)
    : CFWL_WidgetImp(properties, pOuter),
      m_pForm(NULL),
      m_bLButtonDown(FALSE),
      m_iCurSel(-1),
      m_iBtnState(FWL_PARTSTATE_CMB_Normal),
      m_fComboFormHandler(0),
      m_bNeedShowList(FALSE) {
  m_rtClient.Reset();
  m_rtBtn.Reset();
  m_rtHandler.Reset();
}
CFWL_ComboBoxImp::~CFWL_ComboBoxImp() {
}
FWL_ERR CFWL_ComboBoxImp::GetClassName(CFX_WideString& wsClass) const {
  wsClass = FWL_CLASS_ComboBox;
  return FWL_ERR_Succeeded;
}
FX_DWORD CFWL_ComboBoxImp::GetClassID() const {
  return FWL_CLASSHASH_ComboBox;
}
FWL_ERR CFWL_ComboBoxImp::Initialize() {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_Initialize();
  }
  if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
    return FWL_WGTSTATE_Invisible;  // Probably a bug; not a FWL_ERR_ value.
  m_pDelegate = new CFWL_ComboBoxImpDelegate(this);
  CFWL_WidgetImpProperties prop;
  prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
  prop.m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
  if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) {
    prop.m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon;
  }
  prop.m_pDataProvider = m_pProperties->m_pDataProvider;
  m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface));
  m_pListBox->Initialize();
  if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) {
    CFWL_WidgetImpProperties prop2;
    m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop2, m_pInterface));
    m_pEdit->Initialize();
    static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
  }
  if (m_pEdit) {
    m_pEdit->SetParent(m_pInterface);
  }
  SetStates(m_pProperties->m_dwStates);
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::Finalize() {
  if (m_pEdit) {
    m_pEdit->Finalize();
  }
  m_pListBox->Finalize();
  delete m_pDelegate;
  m_pDelegate = nullptr;
  return CFWL_WidgetImp::Finalize();
}
FWL_ERR CFWL_ComboBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) {
  if (bAutoSize) {
    rect.Reset();
    FX_BOOL bIsDropDown = IsDropDownStyle();
    if (bIsDropDown && m_pEdit) {
      m_pEdit->GetWidgetRect(rect, TRUE);
    } else {
      rect.width = 100;
      rect.height = 16;
    }
    if (!m_pProperties->m_pThemeProvider) {
      ReSetTheme();
    }
    FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>(
        GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
    if (!pFWidth)
      return FWL_ERR_Indefinite;
    rect.Inflate(0, 0, *pFWidth, 0);
    CFWL_WidgetImp::GetWidgetRect(rect, TRUE);
  } else {
    rect = m_pProperties->m_rtWidget;
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::ModifyStylesEx(FX_DWORD dwStylesExAdded,
                                         FX_DWORD dwStylesExRemoved) {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
  }
  FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;
  FX_BOOL bRemoveDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;
  if (bAddDropDown && !m_pEdit) {
    CFWL_WidgetImpProperties prop;
    m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, nullptr));
    m_pEdit->Initialize();
    static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
    m_pEdit->SetParent(m_pInterface);
  } else if (bRemoveDropDown && m_pEdit) {
    m_pEdit->SetStates(FWL_WGTSTATE_Invisible, TRUE);
  }
  return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
}
FWL_ERR CFWL_ComboBoxImp::Update() {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_Update();
  }
  if (IsLocked()) {
    return FWL_ERR_Indefinite;
  }
  ReSetTheme();
  FX_BOOL bDropDown = IsDropDownStyle();
  if (bDropDown && m_pEdit) {
    ReSetEditAlignment();
  }
  if (m_pProperties->m_pThemeProvider == NULL) {
    m_pProperties->m_pThemeProvider = GetAvailableTheme();
  }
  Layout();
  CFWL_ThemePart part;
  part.m_pWidget = m_pInterface;
  m_fComboFormHandler =
      *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity(
          &part, FWL_WGTCAPACITY_CMB_ComboFormHandler));
  return FWL_ERR_Succeeded;
}
FX_DWORD CFWL_ComboBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_HitTest(fx, fy);
  }
  return CFWL_WidgetImp::HitTest(fx, fy);
}
FWL_ERR CFWL_ComboBoxImp::DrawWidget(CFX_Graphics* pGraphics,
                                     const CFX_Matrix* pMatrix) {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_DrawWidget(pGraphics, pMatrix);
  }
  if (!pGraphics)
    return FWL_ERR_Indefinite;
  if (!m_pProperties->m_pThemeProvider)
    return FWL_ERR_Indefinite;
  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
  FX_BOOL bIsDropDown = IsDropDownStyle();
  if (HasBorder()) {
    DrawBorder(pGraphics, FWL_PART_CMB_Border, pTheme, pMatrix);
  }
  if (HasEdge()) {
    DrawEdge(pGraphics, FWL_PART_CMB_Edge, pTheme, pMatrix);
  }
  if (!bIsDropDown) {
    CFX_RectF rtTextBk(m_rtClient);
    rtTextBk.width -= m_rtBtn.width;
    CFWL_ThemeBackground param;
    param.m_pWidget = m_pInterface;
    param.m_iPart = FWL_PART_CMB_Background;
    param.m_pGraphics = pGraphics;
    if (pMatrix) {
      param.m_matrix.Concat(*pMatrix);
    }
    param.m_rtPart = rtTextBk;
    if (m_iCurSel >= 0) {
      IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>(
          static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
              ->m_pProperties->m_pDataProvider);
      void* p = pData->GetItemData(m_pListBox.get(),
                                   pData->GetItem(m_pListBox.get(), m_iCurSel));
      if (p != NULL) {
        param.m_pData = p;
      }
    }
    if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
      param.m_dwStates = FWL_PARTSTATE_CMB_Disabled;
    } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) &&
               (m_iCurSel >= 0)) {
      param.m_dwStates = FWL_PARTSTATE_CMB_Selected;
    } else {
      param.m_dwStates = FWL_PARTSTATE_CMB_Normal;
    }
    pTheme->DrawBackground(&param);
    if (m_iCurSel >= 0) {
      if (!m_pListBox)
        return FWL_ERR_Indefinite;
      CFX_WideString wsText;
      IFWL_ComboBoxDP* pData =
          static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
      FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
          ->GetItemText(hItem, wsText);
      CFWL_ThemeText param;
      param.m_pWidget = m_pInterface;
      param.m_iPart = FWL_PART_CMB_Caption;
      param.m_dwStates = m_iBtnState;
      param.m_pGraphics = pGraphics;
      param.m_matrix.Concat(*pMatrix);
      param.m_rtPart = rtTextBk;
      param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)
                             ? FWL_PARTSTATE_CMB_Selected
                             : FWL_PARTSTATE_CMB_Normal;
      param.m_wsText = wsText;
      param.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine;
      param.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft;
      pTheme->DrawText(&param);
    }
  }
  {
    CFWL_ThemeBackground param;
    param.m_pWidget = m_pInterface;
    param.m_iPart = FWL_PART_CMB_DropDownButton;
    param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled)
                           ? FWL_PARTSTATE_CMB_Disabled
                           : m_iBtnState;
    param.m_pGraphics = pGraphics;
    param.m_matrix.Concat(*pMatrix);
    param.m_rtPart = m_rtBtn;
    pTheme->DrawBackground(&param);
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) {
  if (!pThemeProvider)
    return FWL_ERR_Indefinite;
  m_pProperties->m_pThemeProvider = pThemeProvider;
  if (m_pListBox && pThemeProvider->IsValidWidget(m_pListBox.get())) {
    m_pListBox->SetThemeProvider(pThemeProvider);
  }
  if (m_pEdit && pThemeProvider->IsValidWidget(m_pEdit.get())) {
    m_pEdit->SetThemeProvider(pThemeProvider);
  }
  return FWL_ERR_Succeeded;
}
int32_t CFWL_ComboBoxImp::GetCurSel() {
  return m_iCurSel;
}
FWL_ERR CFWL_ComboBoxImp::SetCurSel(int32_t iSel) {
  int32_t iCount =
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->CountItems();
  FX_BOOL bClearSel = iSel < 0 || iSel >= iCount;
  FX_BOOL bDropDown = IsDropDownStyle();
  if (bDropDown && m_pEdit) {
    if (bClearSel) {
      m_pEdit->SetText(CFX_WideString());
    } else {
      CFX_WideString wsText;
      IFWL_ComboBoxDP* pData =
          static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
      FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel);
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
          ->GetItemText(hItem, wsText);
      m_pEdit->SetText(wsText);
    }
    m_pEdit->Update();
  }
  m_iCurSel = bClearSel ? -1 : iSel;
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) {
  FX_BOOL bIsDropDown = IsDropDownStyle();
  if (bIsDropDown && m_pEdit) {
    m_pEdit->SetStates(dwStates, bSet);
  }
  if (m_pListBox) {
    m_pListBox->SetStates(dwStates, bSet);
  }
  return CFWL_WidgetImp::SetStates(dwStates, bSet);
}
FWL_ERR CFWL_ComboBoxImp::SetEditText(const CFX_WideString& wsText) {
  if (!m_pEdit)
    return FWL_ERR_Indefinite;
  m_pEdit->SetText(wsText);
  return m_pEdit->Update();
}
int32_t CFWL_ComboBoxImp::GetEditTextLength() const {
  if (!m_pEdit)
    return -1;
  return m_pEdit->GetTextLength();
}
FWL_ERR CFWL_ComboBoxImp::GetEditText(CFX_WideString& wsText,
                                      int32_t nStart,
                                      int32_t nCount) const {
  if (m_pEdit) {
    return m_pEdit->GetText(wsText, nStart, nCount);
  } else if (m_pListBox) {
    IFWL_ComboBoxDP* pData =
        static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
    return m_pListBox->GetItemText(hItem, wsText);
  }
  return FWL_ERR_Indefinite;
}
FWL_ERR CFWL_ComboBoxImp::SetEditSelRange(int32_t nStart, int32_t nCount) {
  if (!m_pEdit)
    return FWL_ERR_Indefinite;
  static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->ClearSelected();
  m_pEdit->AddSelRange(nStart, nCount);
  return FWL_ERR_Succeeded;
}
int32_t CFWL_ComboBoxImp::GetEditSelRange(int32_t nIndex, int32_t& nStart) {
  if (!m_pEdit)
    return -1;
  return m_pEdit->GetSelRange(nIndex, nStart);
}
int32_t CFWL_ComboBoxImp::GetEditLimit() {
  if (!m_pEdit)
    return -1;
  return m_pEdit->GetLimit();
}
FWL_ERR CFWL_ComboBoxImp::SetEditLimit(int32_t nLimit) {
  if (!m_pEdit)
    return FWL_ERR_Indefinite;
  return m_pEdit->SetLimit(nLimit);
}
FWL_ERR CFWL_ComboBoxImp::EditDoClipboard(int32_t iCmd) {
  if (!m_pEdit)
    return FWL_ERR_Indefinite;
  return m_pEdit->DoClipboard(iCmd);
}
FX_BOOL CFWL_ComboBoxImp::EditRedo(const CFX_ByteStringC& bsRecord) {
  if (!m_pEdit)
    return FALSE;
  return m_pEdit->Redo(bsRecord);
}
FX_BOOL CFWL_ComboBoxImp::EditUndo(const CFX_ByteStringC& bsRecord) {
  if (!m_pEdit)
    return FALSE;
  return m_pEdit->Undo(bsRecord);
}
IFWL_ListBox* CFWL_ComboBoxImp::GetListBoxt() {
  return m_pListBox.get();
}
FX_BOOL CFWL_ComboBoxImp::AfterFocusShowDropList() {
  if (!m_bNeedShowList) {
    return FALSE;
  }
  if (m_pEdit) {
    MatchEditText();
  }
  ShowDropList(TRUE);
  m_bNeedShowList = FALSE;
  return TRUE;
}
FX_ERR CFWL_ComboBoxImp::OpenDropDownList(FX_BOOL bActivate) {
  ShowDropList(bActivate);
  return FWL_ERR_Succeeded;
}
FX_BOOL CFWL_ComboBoxImp::EditCanUndo() {
  return m_pEdit->CanUndo();
}
FX_BOOL CFWL_ComboBoxImp::EditCanRedo() {
  return m_pEdit->CanRedo();
}
FX_BOOL CFWL_ComboBoxImp::EditUndo() {
  return m_pEdit->Undo();
}
FX_BOOL CFWL_ComboBoxImp::EditRedo() {
  return m_pEdit->Redo();
}
FX_BOOL CFWL_ComboBoxImp::EditCanCopy() {
  return m_pEdit->CountSelRanges() > 0;
}
FX_BOOL CFWL_ComboBoxImp::EditCanCut() {
  if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) {
    return FALSE;
  }
  return m_pEdit->CountSelRanges() > 0;
}
FX_BOOL CFWL_ComboBoxImp::EditCanSelectAll() {
  return m_pEdit->GetTextLength() > 0;
}
FX_BOOL CFWL_ComboBoxImp::EditCopy(CFX_WideString& wsCopy) {
  return m_pEdit->Copy(wsCopy);
}
FX_BOOL CFWL_ComboBoxImp::EditCut(CFX_WideString& wsCut) {
  return m_pEdit->Cut(wsCut);
}
FX_BOOL CFWL_ComboBoxImp::EditPaste(const CFX_WideString& wsPaste) {
  return m_pEdit->Paste(wsPaste);
}
FX_BOOL CFWL_ComboBoxImp::EditSelectAll() {
  return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded;
}
FX_BOOL CFWL_ComboBoxImp::EditDelete() {
  return m_pEdit->ClearText() == FWL_ERR_Succeeded;
}
FX_BOOL CFWL_ComboBoxImp::EditDeSelect() {
  return m_pEdit->ClearSelections() == FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::GetBBox(CFX_RectF& rect) {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_GetBBox(rect);
  }
  rect = m_pProperties->m_rtWidget;
  if (m_pListBox && IsDropListShowed()) {
    CFX_RectF rtList;
    m_pListBox->GetWidgetRect(rtList);
    rtList.Offset(rect.left, rect.top);
    rect.Union(rtList);
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::EditModifyStylesEx(FX_DWORD dwStylesExAdded,
                                             FX_DWORD dwStylesExRemoved) {
  if (m_pEdit != NULL) {
    return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
  } else {
    return FWL_ERR_Parameter_Invalid;
  }
}
FX_FLOAT CFWL_ComboBoxImp::GetListHeight() {
  return static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider)
      ->GetListHeight(m_pInterface);
}
void CFWL_ComboBoxImp::DrawStretchHandler(CFX_Graphics* pGraphics,
                                          const CFX_Matrix* pMatrix) {
  CFWL_ThemeBackground param;
  param.m_pGraphics = pGraphics;
  param.m_iPart = FWL_PART_CMB_StretcgHandler;
  param.m_dwStates = FWL_PARTSTATE_CMB_Normal;
  param.m_pWidget = m_pInterface;
  if (pMatrix) {
    param.m_matrix.Concat(*pMatrix);
  }
  param.m_rtPart = m_rtHandler;
  m_pProperties->m_pThemeProvider->DrawBackground(&param);
}
void CFWL_ComboBoxImp::ShowDropList(FX_BOOL bActivate) {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_ShowDropList(bActivate);
  }
  FX_BOOL bDropList = IsDropListShowed();
  if (bDropList == bActivate) {
    return;
  }
  if (!m_pForm) {
    InitProxyForm();
  }
  m_pListProxyDelegate->Reset();
  if (bActivate) {
    static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
        ->ChangeSelected(m_iCurSel);
    ReSetListItemAlignment();
    FX_DWORD dwStyleAdd = m_pProperties->m_dwStyleExes &
                          (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw);
    m_pListBox->ModifyStylesEx(dwStyleAdd, 0);
    m_pListBox->GetWidgetRect(m_rtList, TRUE);
    FX_FLOAT fHeight = GetListHeight();
    if (fHeight > 0) {
      if (m_rtList.height > GetListHeight()) {
        m_rtList.height = GetListHeight();
        m_pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll, 0);
      }
    }
    CFX_RectF rtAnchor;
    rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width,
                 m_pProperties->m_rtWidget.height);
    FX_FLOAT fMinHeight = 0;
    if (m_rtList.width < m_rtClient.width) {
      m_rtList.width = m_rtClient.width;
    }
    m_rtProxy = m_rtList;
    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
      m_rtProxy.height += m_fComboFormHandler;
    }
    GetPopupPos(fMinHeight, m_rtProxy.height, rtAnchor, m_rtProxy);
    if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) {
      FX_FLOAT fx = 0;
      FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2;
      TransformTo(NULL, fx, fy);
      m_bUpFormHandler = fy > m_rtProxy.top;
      if (m_bUpFormHandler) {
        m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler);
        m_rtList.top = m_fComboFormHandler;
      } else {
        m_rtHandler.Set(0, m_rtList.height, m_rtList.width,
                        m_fComboFormHandler);
      }
    }
    m_pForm->SetWidgetRect(m_rtProxy);
    m_pForm->Update();
    m_pListBox->SetWidgetRect(m_rtList);
    m_pListBox->Update();
    CFWL_EvtCmbPreDropDown ev;
    ev.m_pSrcTarget = m_pInterface;
    DispatchEvent(&ev);
    m_fItemHeight =
        static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_fItemHeight;
    static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(TRUE);
    m_pForm->DoModal();
    static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(FALSE);
  } else {
    m_pForm->EndDoModal();
    CFWL_EvtCmbCloseUp ev;
    ev.m_pSrcTarget = m_pInterface;
    DispatchEvent(&ev);
    m_bLButtonDown = FALSE;
    static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_bNotifyOwner =
        TRUE;
    SetFocus(TRUE);
  }
}
FX_BOOL CFWL_ComboBoxImp::IsDropListShowed() {
  return m_pForm && !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible);
}
FX_BOOL CFWL_ComboBoxImp::IsDropDownStyle() const {
  return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown;
}
void CFWL_ComboBoxImp::MatchEditText() {
  CFX_WideString wsText;
  m_pEdit->GetText(wsText);
  int32_t iMatch =
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->MatchItem(wsText);
  if (iMatch != m_iCurSel) {
    static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
        ->ChangeSelected(iMatch);
    if (iMatch >= 0) {
      SynchrEditText(iMatch);
    }
  } else if (iMatch >= 0) {
    static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
  }
  m_iCurSel = iMatch;
}
void CFWL_ComboBoxImp::SynchrEditText(int32_t iListItem) {
  CFX_WideString wsText;
  IFWL_ComboBoxDP* pData =
      static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
  FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iListItem);
  static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
      ->GetItemText(hItem, wsText);
  m_pEdit->SetText(wsText);
  m_pEdit->Update();
  static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
}
void CFWL_ComboBoxImp::Layout() {
  if (m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_Layout();
  }
  GetClientRect(m_rtClient);
  FX_FLOAT* pFWidth =
      static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
  if (!pFWidth)
    return;
  FX_FLOAT fBtn = *pFWidth;
  m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn,
              m_rtClient.height);
  FX_BOOL bIsDropDown = IsDropDownStyle();
  if (bIsDropDown && m_pEdit) {
    CFX_RectF rtEdit;
    rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn,
               m_rtClient.height);
    m_pEdit->SetWidgetRect(rtEdit);
    if (m_iCurSel >= 0) {
      CFX_WideString wsText;
      IFWL_ComboBoxDP* pData =
          static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
      FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
          ->GetItemText(hItem, wsText);
      m_pEdit->LockUpdate();
      m_pEdit->SetText(wsText);
      m_pEdit->UnlockUpdate();
    }
    m_pEdit->Update();
  }
}
void CFWL_ComboBoxImp::ReSetTheme() {
  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
  if (!pTheme) {
    pTheme = GetAvailableTheme();
    m_pProperties->m_pThemeProvider = pTheme;
  }
  if (m_pListBox) {
    if (!m_pListBox->GetThemeProvider() &&
        pTheme->IsValidWidget(m_pListBox.get())) {
      m_pListBox->SetThemeProvider(pTheme);
    }
  }
  if (m_pEdit) {
    if (!m_pEdit->GetThemeProvider() && pTheme->IsValidWidget(m_pEdit.get())) {
      m_pEdit->SetThemeProvider(pTheme);
    }
  }
}
void CFWL_ComboBoxImp::ReSetEditAlignment() {
  if (!m_pEdit)
    return;
  FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;
  FX_DWORD dwAdd = 0;
  switch (dwStylExes & FWL_STYLEEXT_CMB_EditHAlignMask) {
    case FWL_STYLEEXT_CMB_EditHCenter: {
      dwAdd |= FWL_STYLEEXT_EDT_HCenter;
      break;
    }
    case FWL_STYLEEXT_CMB_EditHFar: {
      dwAdd |= FWL_STYLEEXT_EDT_HFar;
      break;
    }
    default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; }
  }
  switch (dwStylExes & FWL_STYLEEXT_CMB_EditVAlignMask) {
    case FWL_STYLEEXT_CMB_EditVCenter: {
      dwAdd |= FWL_STYLEEXT_EDT_VCenter;
      break;
    }
    case FWL_STYLEEXT_CMB_EditVFar: {
      dwAdd |= FWL_STYLEEXT_EDT_VFar;
      break;
    }
    default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; }
  }
  if (dwStylExes & FWL_STYLEEXT_CMB_EditJustified) {
    dwAdd |= FWL_STYLEEXT_EDT_Justified;
  }
  if (dwStylExes & FWL_STYLEEXT_CMB_EditDistributed) {
    dwAdd |= FWL_STYLEEXT_EDT_Distributed;
  }
  m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask |
                                     FWL_STYLEEXT_EDT_HAlignModeMask |
                                     FWL_STYLEEXT_EDT_VAlignMask);
}
void CFWL_ComboBoxImp::ReSetListItemAlignment() {
  if (!m_pListBox)
    return;
  FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes;
  FX_DWORD dwAdd = 0;
  switch (dwStylExes & FWL_STYLEEXT_CMB_ListItemAlignMask) {
    case FWL_STYLEEXT_CMB_ListItemCenterAlign: {
      dwAdd |= FWL_STYLEEXT_LTB_CenterAlign;
    }
    case FWL_STYLEEXT_CMB_ListItemRightAlign: {
      dwAdd |= FWL_STYLEEXT_LTB_RightAlign;
    }
    default: { dwAdd |= FWL_STYLEEXT_LTB_LeftAlign; }
  }
  m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask);
}
void CFWL_ComboBoxImp::ProcessSelChanged(FX_BOOL bLButtonUp) {
  IFWL_ComboBoxDP* pDatas =
      static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
  m_iCurSel = pDatas->GetItemIndex(m_pInterface, m_pListBox->GetSelItem(0));
  FX_BOOL bDropDown = IsDropDownStyle();
  if (bDropDown) {
    IFWL_ComboBoxDP* pData =
        static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
    FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
    if (hItem) {
      CFX_WideString wsText;
      pData->GetItemText(m_pInterface, hItem, wsText);
      if (m_pEdit) {
        m_pEdit->SetText(wsText);
        m_pEdit->Update();
        static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected();
      }
      CFWL_EvtCmbSelChanged ev;
      ev.bLButtonUp = bLButtonUp;
      ev.m_pSrcTarget = m_pInterface;
      ev.iArraySels.Add(m_iCurSel);
      DispatchEvent(&ev);
    }
  } else {
    Repaint(&m_rtClient);
  }
}
void CFWL_ComboBoxImp::InitProxyForm() {
  if (m_pForm)
    return;
  if (!m_pListBox)
    return;
  CFWL_WidgetImpProperties propForm;
  propForm.m_pOwner = m_pInterface;
  propForm.m_dwStyles = FWL_WGTSTYLE_Popup;
  propForm.m_dwStates = FWL_WGTSTATE_Invisible;
  CFX_WideString className;
  m_pForm = IFWL_Form::CreateFormProxy(propForm, &className, m_pListBox.get());
  m_pForm->Initialize();
  m_pProxy = static_cast<CFWL_FormProxyImp*>(m_pForm->GetImpl());
  m_pListBox->SetParent(m_pForm);
  m_pListProxyDelegate = new CFWL_ComboProxyImpDelegate(m_pForm, this);
  m_pProxy->SetDelegate(m_pListProxyDelegate);
}
FWL_ERR CFWL_ComboBoxImp::DisForm_Initialize() {
  if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded)
    return FWL_WGTSTATE_Invisible;  // Ditto.
  m_pDelegate = new CFWL_ComboBoxImpDelegate(this);
  DisForm_InitComboList();
  DisForm_InitComboEdit();
  return FWL_ERR_Succeeded;
}
void CFWL_ComboBoxImp::DisForm_InitComboList() {
  if (m_pListBox) {
    return;
  }
  CFWL_WidgetImpProperties prop;
  prop.m_pParent = m_pInterface;
  prop.m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll;
  prop.m_dwStates = FWL_WGTSTATE_Invisible;
  prop.m_pDataProvider = m_pProperties->m_pDataProvider;
  prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
  m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface));
  m_pListBox->Initialize();
}
void CFWL_ComboBoxImp::DisForm_InitComboEdit() {
  if (m_pEdit) {
    return;
  }
  CFWL_WidgetImpProperties prop;
  prop.m_pParent = m_pInterface;
  prop.m_pThemeProvider = m_pProperties->m_pThemeProvider;
  m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, m_pInterface));
  m_pEdit->Initialize();
  static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface);
}
void CFWL_ComboBoxImp::DisForm_ShowDropList(FX_BOOL bActivate) {
  FX_BOOL bDropList = DisForm_IsDropListShowed();
  if (bDropList == bActivate) {
    return;
  }
  if (bActivate) {
    CFWL_EvtCmbPreDropDown preEvent;
    preEvent.m_pSrcTarget = m_pInterface;
    DispatchEvent(&preEvent);
    CFWL_ComboListImp* pComboList =
        static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl());
    int32_t iItems = pComboList->CountItems();
    if (iItems < 1) {
      return;
    }
    ReSetListItemAlignment();
    pComboList->ChangeSelected(m_iCurSel);
    FX_FLOAT fItemHeight = pComboList->GetItemHeigt();
    FX_FLOAT fBorder = GetBorderSize();
    FX_FLOAT fPopupMin = 0.0f;
    if (iItems > 3) {
      fPopupMin = fItemHeight * 3 + fBorder * 2;
    }
    FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2;
    CFX_RectF rtList;
    rtList.left = m_rtClient.left;
    rtList.width = m_pProperties->m_rtWidget.width;
    rtList.top = 0;
    rtList.height = 0;
    GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList);
    m_pListBox->SetWidgetRect(rtList);
    m_pListBox->Update();
  } else {
    SetFocus(TRUE);
  }
  m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate);
  if (bActivate) {
    CFWL_EvtCmbPostDropDown postEvent;
    postEvent.m_pSrcTarget = m_pInterface;
    DispatchEvent(&postEvent);
  }
  CFX_RectF rect;
  m_pListBox->GetWidgetRect(rect);
  rect.Inflate(2, 2);
  Repaint(&rect);
}
FX_BOOL CFWL_ComboBoxImp::DisForm_IsDropListShowed() {
  return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible);
}
FWL_ERR CFWL_ComboBoxImp::DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded,
                                                 FX_DWORD dwStylesExRemoved) {
  if (!m_pEdit) {
    DisForm_InitComboEdit();
  }
  FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown;
  FX_BOOL bDelDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown;
  dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown;
  m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown;
  if (bAddDropDown) {
    m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly);
  } else if (bDelDropDown) {
    m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0);
  }
  return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved);
}
FWL_ERR CFWL_ComboBoxImp::DisForm_Update() {
  if (m_iLock) {
    return FWL_ERR_Indefinite;
  }
  if (m_pEdit) {
    ReSetEditAlignment();
  }
  ReSetTheme();
  Layout();
  return FWL_ERR_Succeeded;
}
FX_DWORD CFWL_ComboBoxImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) {
  CFX_RectF rect;
  rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width,
           m_pProperties->m_rtWidget.height);
  if (rect.Contains(fx, fy)) {
    return FWL_WGTHITTEST_Edit;
  }
  if (m_rtBtn.Contains(fx, fy)) {
    return FWL_WGTHITTEST_Client;
  }
  if (DisForm_IsDropListShowed()) {
    m_pListBox->GetWidgetRect(rect);
    if (rect.Contains(fx, fy)) {
      return FWL_WGTHITTEST_Client;
    }
  }
  return FWL_WGTHITTEST_Unknown;
}
FWL_ERR CFWL_ComboBoxImp::DisForm_DrawWidget(CFX_Graphics* pGraphics,
                                             const CFX_Matrix* pMatrix) {
  IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider;
  CFX_Matrix mtOrg;
  mtOrg.Set(1, 0, 0, 1, 0, 0);
  if (pMatrix) {
    mtOrg = *pMatrix;
  }
  FX_BOOL bListShowed = m_pListBox && DisForm_IsDropListShowed();
  pGraphics->SaveGraphState();
  pGraphics->ConcatMatrix(&mtOrg);
  if (!m_rtBtn.IsEmpty(0.1f)) {
    CFWL_ThemeBackground param;
    param.m_pWidget = m_pInterface;
    param.m_iPart = FWL_PART_CMB_DropDownButton;
    param.m_dwStates = m_iBtnState;
    param.m_pGraphics = pGraphics;
    param.m_rtPart = m_rtBtn;
    pTheme->DrawBackground(&param);
  }
  pGraphics->RestoreGraphState();
  if (m_pEdit) {
    CFX_RectF rtEdit;
    m_pEdit->GetWidgetRect(rtEdit);
    CFX_Matrix mt;
    mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top);
    mt.Concat(mtOrg);
    m_pEdit->DrawWidget(pGraphics, &mt);
  }
  if (bListShowed) {
    CFX_RectF rtList;
    m_pListBox->GetWidgetRect(rtList);
    CFX_Matrix mt;
    mt.Set(1, 0, 0, 1, rtList.left, rtList.top);
    mt.Concat(mtOrg);
    m_pListBox->DrawWidget(pGraphics, &mt);
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImp::DisForm_GetBBox(CFX_RectF& rect) {
  rect = m_pProperties->m_rtWidget;
  if (m_pListBox && DisForm_IsDropListShowed()) {
    CFX_RectF rtList;
    m_pListBox->GetWidgetRect(rtList);
    rtList.Offset(rect.left, rect.top);
    rect.Union(rtList);
  }
  return FWL_ERR_Succeeded;
}
void CFWL_ComboBoxImp::DisForm_Layout() {
  GetClientRect(m_rtClient);
  m_rtContent = m_rtClient;
  FX_FLOAT* pFWidth =
      static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth));
  if (!pFWidth)
    return;
  FX_FLOAT borderWidth = 0;
  { borderWidth = FWL_PART_CMB_Border; }
  FX_FLOAT fBtn = *pFWidth;
  if (!(GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) {
    m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth,
                fBtn - borderWidth, m_rtClient.height - 2 * borderWidth);
  }
  CFX_RectF* pUIMargin =
      static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin));
  if (pUIMargin) {
    m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width,
                        pUIMargin->height);
  }
  FX_BOOL bIsDropDown = IsDropDownStyle();
  if (bIsDropDown && m_pEdit) {
    CFX_RectF rtEdit;
    rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn,
               m_rtContent.height);
    m_pEdit->SetWidgetRect(rtEdit);
    if (m_iCurSel >= 0) {
      CFX_WideString wsText;
      IFWL_ComboBoxDP* pData =
          static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider);
      FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel);
      static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())
          ->GetItemText(hItem, wsText);
      m_pEdit->LockUpdate();
      m_pEdit->SetText(wsText);
      m_pEdit->UnlockUpdate();
    }
    m_pEdit->Update();
  }
}
CFWL_ComboBoxImpDelegate::CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp* pOwner)
    : m_pOwner(pOwner) {}
int32_t CFWL_ComboBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
  if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) {
    return DisForm_OnProcessMessage(pMessage);
  }
  if (!pMessage)
    return 0;
  FX_DWORD dwMsgCode = pMessage->GetClassID();
  FX_BOOL iRet = 1;
  switch (dwMsgCode) {
    case FWL_MSGHASH_SetFocus:
    case FWL_MSGHASH_KillFocus: {
      OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
      break;
    }
    case FWL_MSGHASH_Mouse: {
      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
      FX_DWORD dwCmd = pMsg->m_dwCmd;
      switch (dwCmd) {
        case FWL_MSGMOUSECMD_LButtonDown: {
          OnLButtonDown(pMsg);
          break;
        }
        case FWL_MSGMOUSECMD_LButtonUp: {
          OnLButtonUp(pMsg);
          break;
        }
        case FWL_MSGMOUSECMD_MouseMove: {
          OnMouseMove(pMsg);
          break;
        }
        case FWL_MSGMOUSECMD_MouseLeave: {
          OnMouseLeave(pMsg);
          break;
        }
        default: {}
      }
      break;
    }
    case FWL_MSGHASH_Key: {
      OnKey(static_cast<CFWL_MsgKey*>(pMessage));
      break;
    }
    default: { iRet = 0; }
  }
  CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
  return iRet;
}
FWL_ERR CFWL_ComboBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) {
  FX_DWORD dwFlag = pEvent->GetClassID();
  if (dwFlag == FWL_EVTHASH_LTB_DrawItem) {
    CFWL_EvtLtbDrawItem* pDrawItemEvent =
        static_cast<CFWL_EvtLtbDrawItem*>(pEvent);
    CFWL_EvtCmbDrawItem pTemp;
    pTemp.m_pSrcTarget = m_pOwner->m_pInterface;
    pTemp.m_pGraphics = pDrawItemEvent->m_pGraphics;
    pTemp.m_index = pDrawItemEvent->m_index;
    pTemp.m_rtItem = pDrawItemEvent->m_rect;
    m_pOwner->DispatchEvent(&pTemp);
  } else if (dwFlag == FWL_EVTHASH_Scroll) {
    CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent);
    CFWL_EvtScroll pScrollEv;
    pScrollEv.m_pSrcTarget = m_pOwner->m_pInterface;
    pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode;
    pScrollEv.m_fPos = pScrollEvent->m_fPos;
    m_pOwner->DispatchEvent(&pScrollEv);
  } else if (dwFlag == FWL_EVTHASH_EDT_TextChanged) {
    CFWL_EvtEdtTextChanged* pTextChangedEvent =
        static_cast<CFWL_EvtEdtTextChanged*>(pEvent);
    CFWL_EvtCmbEditChanged pTemp;
    pTemp.m_pSrcTarget = m_pOwner->m_pInterface;
    pTemp.wsInsert = pTextChangedEvent->wsInsert;
    pTemp.wsDelete = pTextChangedEvent->wsDelete;
    pTemp.nChangeType = pTextChangedEvent->nChangeType;
    m_pOwner->DispatchEvent(&pTemp);
  }
  return FWL_ERR_Succeeded;
}
FWL_ERR CFWL_ComboBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
                                               const CFX_Matrix* pMatrix) {
  return m_pOwner->DrawWidget(pGraphics, pMatrix);
}
void CFWL_ComboBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg,
                                              FX_BOOL bSet) {
  IFWL_Target* pDstTarget = pMsg->m_pDstTarget;
  IFWL_Target* pSrcTarget = pMsg->m_pSrcTarget;
  FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
  if (bSet) {
    m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
    if (bDropDown && pSrcTarget != m_pOwner->m_pListBox.get()) {
      if (!m_pOwner->m_pEdit)
        return;
      static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
          ->SetSelected();
    } else {
      m_pOwner->Repaint(&m_pOwner->m_rtClient);
    }
  } else {
    m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    if (bDropDown && pDstTarget != m_pOwner->m_pListBox.get()) {
      if (!m_pOwner->m_pEdit)
        return;
      static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
          ->FlagFocus(FALSE);
      static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl())
          ->ClearSelected();
    } else {
      m_pOwner->Repaint(&m_pOwner->m_rtClient);
    }
  }
}
void CFWL_ComboBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
  if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) {
    return;
  }
  FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
  CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;
  FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);
  if (bClickBtn) {
    if (bDropDown && m_pOwner->m_pEdit) {
      m_pOwner->MatchEditText();
    }
    m_pOwner->m_bLButtonDown = TRUE;
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Pressed;
    m_pOwner->Repaint(&m_pOwner->m_rtClient);
    m_pOwner->ShowDropList(TRUE);
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
    m_pOwner->Repaint(&m_pOwner->m_rtClient);
  }
}
void CFWL_ComboBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
  m_pOwner->m_bLButtonDown = FALSE;
  if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Hovered;
  } else {
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
  }
  m_pOwner->Repaint(&m_pOwner->m_rtBtn);
}
void CFWL_ComboBoxImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
  int32_t iOldState = m_pOwner->m_iBtnState;
  if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) {
    m_pOwner->m_iBtnState = m_pOwner->m_bLButtonDown
                                ? FWL_PARTSTATE_CMB_Pressed
                                : FWL_PARTSTATE_CMB_Hovered;
  } else {
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
  }
  if ((iOldState != m_pOwner->m_iBtnState) &&
      !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
        FWL_WGTSTATE_Disabled)) {
    m_pOwner->Repaint(&m_pOwner->m_rtBtn);
  }
}
void CFWL_ComboBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) {
  if (!m_pOwner->IsDropListShowed() &&
      !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) ==
        FWL_WGTSTATE_Disabled)) {
    m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal;
    m_pOwner->Repaint(&m_pOwner->m_rtBtn);
  }
}
void CFWL_ComboBoxImpDelegate::OnKey(CFWL_MsgKey* pMsg) {
  FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
  if (dwKeyCode == FWL_VKEY_Tab) {
    m_pOwner->DispatchKeyEvent(pMsg);
    return;
  }
  if (pMsg->m_pDstTarget == m_pOwner->m_pInterface)
    DoSubCtrlKey(pMsg);
}
void CFWL_ComboBoxImpDelegate::DoSubCtrlKey(CFWL_MsgKey* pMsg) {
  FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
  const bool bUp = dwKeyCode == FWL_VKEY_Up;
  const bool bDown = dwKeyCode == FWL_VKEY_Down;
  if (bUp || bDown) {
    int32_t iCount = static_cast<CFWL_ComboListImp*>(
                         m_pOwner->m_pListBox->GetImpl())->CountItems();
    if (iCount < 1) {
      return;
    }
    FX_BOOL bMatchEqual = FALSE;
    int32_t iCurSel = m_pOwner->m_iCurSel;
    FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
    if (bDropDown && m_pOwner->m_pEdit) {
      CFX_WideString wsText;
      m_pOwner->m_pEdit->GetText(wsText);
      iCurSel = static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl())
                    ->MatchItem(wsText);
      if (iCurSel >= 0) {
        CFX_WideString wsTemp;
        IFWL_ComboBoxDP* pData = static_cast<IFWL_ComboBoxDP*>(
            m_pOwner->m_pProperties->m_pDataProvider);
        FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, iCurSel);
        static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl())
            ->GetItemText(hItem, wsTemp);
        bMatchEqual = wsText.Equal(wsTemp);
      }
    }
    if (iCurSel < 0) {
      iCurSel = 0;
    } else if (!bDropDown || bMatchEqual) {
      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {
        return;
      }
      if (bUp) {
        iCurSel--;
      } else {
        iCurSel++;
      }
    }
    m_pOwner->m_iCurSel = iCurSel;
    if (bDropDown && m_pOwner->m_pEdit) {
      m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);
    } else {
      m_pOwner->Repaint(&m_pOwner->m_rtClient);
    }
    return;
  }
  FX_BOOL bDropDown = m_pOwner->IsDropDownStyle();
  if (bDropDown) {
    IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
    pDelegate->OnProcessMessage(pMsg);
  }
}
int32_t CFWL_ComboBoxImpDelegate::DisForm_OnProcessMessage(
    CFWL_Message* pMessage) {
  if (!pMessage)
    return 0;
  FX_DWORD dwMsgCode = pMessage->GetClassID();
  FX_BOOL backDefault = TRUE;
  switch (dwMsgCode) {
    case FWL_MSGHASH_SetFocus:
    case FWL_MSGHASH_KillFocus: {
      backDefault = FALSE;
      DisForm_OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus);
      break;
    }
    case FWL_MSGHASH_Mouse: {
      backDefault = FALSE;
      CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
      FX_DWORD dwCmd = pMsg->m_dwCmd;
      switch (dwCmd) {
        case FWL_MSGMOUSECMD_LButtonDown: {
          DisForm_OnLButtonDown(pMsg);
          break;
        }
        case FWL_MSGMOUSECMD_LButtonUp: {
          OnLButtonUp(pMsg);
          break;
        }
        default: {}
      }
      break;
    }
    case FWL_MSGHASH_Key: {
      backDefault = FALSE;
      CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage);
      if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyUp) {
        break;
      }
      if (m_pOwner->DisForm_IsDropListShowed() &&
          pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) {
        FX_DWORD dwKeyCode = pKey->m_dwKeyCode;
        FX_BOOL bListKey =
            dwKeyCode == FWL_VKEY_Up || dwKeyCode == FWL_VKEY_Down ||
            dwKeyCode == FWL_VKEY_Return || dwKeyCode == FWL_VKEY_Escape;
        if (bListKey) {
          IFWL_WidgetDelegate* pDelegate =
              m_pOwner->m_pListBox->SetDelegate(NULL);
          pDelegate->OnProcessMessage(pMessage);
          break;
        }
      }
      DisForm_OnKey(pKey);
      break;
    }
    default: {}
  }
  if (!backDefault) {
    return 1;
  }
  return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
}
void CFWL_ComboBoxImpDelegate::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) {
  FX_BOOL bDropDown = m_pOwner->DisForm_IsDropListShowed();
  CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient;
  FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy);
  if (bClickBtn) {
    if (m_pOwner->DisForm_IsDropListShowed()) {
      m_pOwner->DisForm_ShowDropList(FALSE);
      return;
    }
    {
      if (m_pOwner->m_pEdit) {
        m_pOwner->MatchEditText();
      }
      m_pOwner->DisForm_ShowDropList(TRUE);
    }
  }
}
void CFWL_ComboBoxImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg,
                                                      FX_BOOL bSet) {
  if (bSet) {
    m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused;
    if ((m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) {
      CFWL_MsgSetFocus msg;
      msg.m_pDstTarget = m_pOwner->m_pEdit.get();
      msg.m_pSrcTarget = NULL;
      IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
      pDelegate->OnProcessMessage(&msg);
    }
  } else {
    m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused;
    m_pOwner->DisForm_ShowDropList(FALSE);
    CFWL_MsgKillFocus msg;
    msg.m_pDstTarget = NULL;
    msg.m_pSrcTarget = m_pOwner->m_pEdit.get();
    IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
    pDelegate->OnProcessMessage(&msg);
  }
}
void CFWL_ComboBoxImpDelegate::DisForm_OnKey(CFWL_MsgKey* pMsg) {
  FX_DWORD dwKeyCode = pMsg->m_dwKeyCode;
  const bool bUp = dwKeyCode == FWL_VKEY_Up;
  const bool bDown = dwKeyCode == FWL_VKEY_Down;
  if (bUp || bDown) {
    CFWL_ComboListImp* pComboList =
        static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl());
    int32_t iCount = pComboList->CountItems();
    if (iCount < 1) {
      return;
    }
    FX_BOOL bMatchEqual = FALSE;
    int32_t iCurSel = m_pOwner->m_iCurSel;
    if (m_pOwner->m_pEdit) {
      CFX_WideString wsText;
      m_pOwner->m_pEdit->GetText(wsText);
      iCurSel = pComboList->MatchItem(wsText);
      if (iCurSel >= 0) {
        CFX_WideString wsTemp;
        FWL_HLISTITEM item = m_pOwner->m_pListBox->GetSelItem(iCurSel);
        m_pOwner->m_pListBox->GetItemText(item, wsTemp);
        bMatchEqual = wsText.Equal(wsTemp);
      }
    }
    if (iCurSel < 0) {
      iCurSel = 0;
    } else if (bMatchEqual) {
      if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) {
        return;
      }
      if (bUp) {
        iCurSel--;
      } else {
        iCurSel++;
      }
    }
    m_pOwner->m_iCurSel = iCurSel;
    m_pOwner->SynchrEditText(m_pOwner->m_iCurSel);
    return;
  }
  if (m_pOwner->m_pEdit) {
    IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL);
    pDelegate->OnProcessMessage(pMsg);
  }
}
CFWL_ComboProxyImpDelegate::CFWL_ComboProxyImpDelegate(
    IFWL_Form* pForm,
    CFWL_ComboBoxImp* pComboBox)
    : m_bLButtonDown(FALSE),
      m_bLButtonUpSelf(FALSE),
      m_fStartPos(0),
      m_pForm(pForm),
      m_pComboBox(pComboBox) {
}
int32_t CFWL_ComboProxyImpDelegate::OnProcessMessage(CFWL_Message* pMessage) {
  if (!pMessage)
    return 0;
  FX_DWORD dwMsgCode = pMessage->GetClassID();
  if (dwMsgCode == FWL_MSGHASH_Mouse) {
    CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage);
    FX_DWORD dwCmd = pMsg->m_dwCmd;
    switch (dwCmd) {
      case FWL_MSGMOUSECMD_LButtonDown: {
        OnLButtonDown(pMsg);
        break;
      }
      case FWL_MSGMOUSECMD_LButtonUp: {
        OnLButtonUp(pMsg);
        break;
      }
      case FWL_MSGMOUSECMD_MouseMove: {
        OnMouseMove(pMsg);
        break;
      }
      default: {}
    }
  }
  if (dwMsgCode == FWL_MSGHASH_Deactivate) {
    OnDeactive(static_cast<CFWL_MsgDeactivate*>(pMessage));
  }
  if (dwMsgCode == FWL_MSGHASH_KillFocus || dwMsgCode == FWL_MSGHASH_SetFocus) {
    OnFocusChanged(static_cast<CFWL_MsgKillFocus*>(pMessage),
                   dwMsgCode == FWL_MSGHASH_SetFocus);
  }
  return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage);
}
FWL_ERR CFWL_ComboProxyImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics,
                                                 const CFX_Matrix* pMatrix) {
  m_pComboBox->DrawStretchHandler(pGraphics, pMatrix);
  return FWL_ERR_Succeeded;
}
void CFWL_ComboProxyImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) {
  IFWL_NoteThread* pThread = m_pForm->GetOwnerThread();
  if (!pThread)
    return;
  CFWL_NoteDriver* pDriver =
      static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
  CFX_RectF rtWidget;
  m_pForm->GetWidgetRect(rtWidget);
  rtWidget.left = rtWidget.top = 0;
  if (rtWidget.Contains(pMsg->m_fx, pMsg->m_fy)) {
    m_bLButtonDown = TRUE;
    pDriver->SetGrab(m_pForm, TRUE);
  } else {
    m_bLButtonDown = FALSE;
    pDriver->SetGrab(m_pForm, FALSE);
    m_pComboBox->ShowDropList(FALSE);
  }
}
void CFWL_ComboProxyImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) {
  m_bLButtonDown = FALSE;
  IFWL_NoteThread* pThread = m_pForm->GetOwnerThread();
  if (!pThread)
    return;
  CFWL_NoteDriver* pDriver =
      static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver());
  pDriver->SetGrab(m_pForm, FALSE);
  if (m_bLButtonUpSelf) {
    CFX_RectF rect;
    m_pForm->GetWidgetRect(rect);
    rect.left = rect.top = 0;
    if (!rect.Contains(pMsg->m_fx, pMsg->m_fy) &&
        m_pComboBox->IsDropListShowed()) {
      m_pComboBox->ShowDropList(FALSE);
    }
  } else {
    m_bLButtonUpSelf = TRUE;
  }
}
void CFWL_ComboProxyImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) {
}
void CFWL_ComboProxyImpDelegate::OnDeactive(CFWL_MsgDeactivate* pMsg) {
  m_pComboBox->ShowDropList(FALSE);
}
void CFWL_ComboProxyImpDelegate::OnFocusChanged(CFWL_MsgKillFocus* pMsg,
                                                FX_BOOL bSet) {
  if (!bSet) {
    if (pMsg->m_pSetFocus == NULL) {
      m_pComboBox->ShowDropList(FALSE);
    }
  }
}
