// 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/fxfa/app/xfa_ffchoicelist.h"

#include <vector>

#include "third_party/base/ptr_util.h"
#include "third_party/base/stl_util.h"
#include "xfa/fwl/cfwl_app.h"
#include "xfa/fwl/cfwl_combobox.h"
#include "xfa/fwl/cfwl_edit.h"
#include "xfa/fwl/cfwl_eventselectchanged.h"
#include "xfa/fwl/cfwl_listbox.h"
#include "xfa/fwl/cfwl_notedriver.h"
#include "xfa/fwl/cfwl_widgetproperties.h"
#include "xfa/fxfa/app/xfa_fffield.h"
#include "xfa/fxfa/app/xfa_fwladapter.h"
#include "xfa/fxfa/cxfa_eventparam.h"
#include "xfa/fxfa/xfa_ffdoc.h"
#include "xfa/fxfa/xfa_ffdocview.h"
#include "xfa/fxfa/xfa_ffpageview.h"
#include "xfa/fxfa/xfa_ffwidget.h"

CXFA_FFListBox::CXFA_FFListBox(CXFA_WidgetAcc* pDataAcc)
    : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {}

CXFA_FFListBox::~CXFA_FFListBox() {
  if (m_pNormalWidget) {
    CFWL_NoteDriver* pNoteDriver =
        m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
    pNoteDriver->UnregisterEventTarget(m_pNormalWidget);
  }
}

bool CXFA_FFListBox::LoadWidget() {
  CFWL_ListBox* pListBox = new CFWL_ListBox(
      GetFWLApp(), pdfium::MakeUnique<CFWL_WidgetProperties>(), nullptr);
  pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll | FWL_WGTSTYLE_NoBackground,
                         0xFFFFFFFF);
  m_pNormalWidget = (CFWL_Widget*)pListBox;
  m_pNormalWidget->SetLayoutItem(this);

  CFWL_NoteDriver* pNoteDriver =
      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);

  m_pOldDelegate = m_pNormalWidget->GetDelegate();
  m_pNormalWidget->SetDelegate(this);
  m_pNormalWidget->LockUpdate();

  std::vector<CFX_WideString> wsLabelArray;
  m_pDataAcc->GetChoiceListItems(wsLabelArray, false);
  int32_t iItems = pdfium::CollectionSize<int32_t>(wsLabelArray);
  for (int32_t i = 0; i < iItems; i++) {
    pListBox->AddString(wsLabelArray[i].AsStringC());
  }
  uint32_t dwExtendedStyle = FWL_STYLEEXT_LTB_ShowScrollBarFocus;
  if (m_pDataAcc->GetChoiceListOpen() == XFA_ATTRIBUTEENUM_MultiSelect) {
    dwExtendedStyle |= FWL_STYLEEXT_LTB_MultiSelection;
  }
  dwExtendedStyle |= GetAlignment();
  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
  CFX_ArrayTemplate<int32_t> iSelArray;
  m_pDataAcc->GetSelectedItems(iSelArray);
  int32_t iSelCount = iSelArray.GetSize();
  for (int32_t j = 0; j < iSelCount; j++) {
    CFWL_ListItem* item = pListBox->GetItem(nullptr, iSelArray[j]);
    pListBox->SetSelItem(item, true);
  }
  m_pNormalWidget->UnlockUpdate();
  return CXFA_FFField::LoadWidget();
}

bool CXFA_FFListBox::OnKillFocus(CXFA_FFWidget* pNewFocus) {
  if (!ProcessCommittedData())
    UpdateFWLData();
  CXFA_FFField::OnKillFocus(pNewFocus);
  return true;
}

bool CXFA_FFListBox::CommitData() {
  CFWL_ListBox* pListBox = static_cast<CFWL_ListBox*>(m_pNormalWidget);
  int32_t iSels = pListBox->CountSelItems();
  CFX_ArrayTemplate<int32_t> iSelArray;
  for (int32_t i = 0; i < iSels; ++i)
    iSelArray.Add(pListBox->GetSelIndex(i));
  m_pDataAcc->SetSelectedItems(iSelArray, true, false, true);
  return true;
}

bool CXFA_FFListBox::IsDataChanged() {
  CFX_ArrayTemplate<int32_t> iSelArray;
  m_pDataAcc->GetSelectedItems(iSelArray);
  int32_t iOldSels = iSelArray.GetSize();
  CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget;
  int32_t iSels = pListBox->CountSelItems();
  if (iOldSels != iSels)
    return true;

  for (int32_t i = 0; i < iSels; ++i) {
    CFWL_ListItem* hlistItem = pListBox->GetItem(nullptr, iSelArray[i]);
    if (!(hlistItem->GetStates() & FWL_ITEMSTATE_LTB_Selected))
      return true;
  }
  return false;
}

uint32_t CXFA_FFListBox::GetAlignment() {
  uint32_t dwExtendedStyle = 0;
  if (CXFA_Para para = m_pDataAcc->GetPara()) {
    int32_t iHorz = para.GetHorizontalAlign();
    switch (iHorz) {
      case XFA_ATTRIBUTEENUM_Center:
        dwExtendedStyle |= FWL_STYLEEXT_LTB_CenterAlign;
        break;
      case XFA_ATTRIBUTEENUM_Justify:
        break;
      case XFA_ATTRIBUTEENUM_JustifyAll:
        break;
      case XFA_ATTRIBUTEENUM_Radix:
        break;
      case XFA_ATTRIBUTEENUM_Right:
        dwExtendedStyle |= FWL_STYLEEXT_LTB_RightAlign;
        break;
      default:
        dwExtendedStyle |= FWL_STYLEEXT_LTB_LeftAlign;
        break;
    }
  }
  return dwExtendedStyle;
}
bool CXFA_FFListBox::UpdateFWLData() {
  if (!m_pNormalWidget) {
    return false;
  }
  CFWL_ListBox* pListBox = ((CFWL_ListBox*)m_pNormalWidget);
  CFX_ArrayTemplate<CFWL_ListItem*> selItemArray;
  CFX_ArrayTemplate<int32_t> iSelArray;
  m_pDataAcc->GetSelectedItems(iSelArray);
  int32_t iSelCount = iSelArray.GetSize();
  for (int32_t j = 0; j < iSelCount; j++) {
    CFWL_ListItem* lpItemSel = pListBox->GetSelItem(iSelArray[j]);
    selItemArray.Add(lpItemSel);
  }
  pListBox->SetSelItem(pListBox->GetSelItem(-1), false);
  for (int32_t i = 0; i < iSelCount; i++) {
    ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(selItemArray[i], true);
  }
  m_pNormalWidget->Update();
  return true;
}
void CXFA_FFListBox::OnSelectChanged(
    CFWL_Widget* pWidget,
    const CFX_ArrayTemplate<int32_t>& arrSels) {
  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_Change;
  eParam.m_pTarget = m_pDataAcc;
  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
  CFWL_ListBox* pListBox = (CFWL_ListBox*)m_pNormalWidget;
  int32_t iSels = pListBox->CountSelItems();
  if (iSels > 0) {
    CFWL_ListItem* item = pListBox->GetSelItem(0);
    eParam.m_wsNewText = item ? item->GetText() : L"";
  }

  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, &eParam);
}
void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) {
  CFWL_ListItem* item = ((CFWL_ListBox*)m_pNormalWidget)->GetSelItem(nIndex);
  ((CFWL_ListBox*)m_pNormalWidget)->SetSelItem(item, bSelected);
  m_pNormalWidget->Update();
  AddInvalidateRect();
}
void CXFA_FFListBox::InsertItem(const CFX_WideStringC& wsLabel,
                                int32_t nIndex) {
  CFX_WideString wsTemp(wsLabel);
  ((CFWL_ListBox*)m_pNormalWidget)->AddString(wsTemp.AsStringC());
  m_pNormalWidget->Update();
  AddInvalidateRect();
}
void CXFA_FFListBox::DeleteItem(int32_t nIndex) {
  CFWL_ListBox* listBox = static_cast<CFWL_ListBox*>(m_pNormalWidget);
  if (nIndex < 0)
    listBox->DeleteAll();
  else
    listBox->DeleteString(listBox->GetItem(nullptr, nIndex));

  listBox->Update();
  AddInvalidateRect();
}

void CXFA_FFListBox::OnProcessMessage(CFWL_Message* pMessage) {
  m_pOldDelegate->OnProcessMessage(pMessage);
}

void CXFA_FFListBox::OnProcessEvent(CFWL_Event* pEvent) {
  CXFA_FFField::OnProcessEvent(pEvent);
  switch (pEvent->GetType()) {
    case CFWL_Event::Type::SelectChanged: {
      CFX_ArrayTemplate<int32_t> arrSels;
      OnSelectChanged(m_pNormalWidget, arrSels);
      break;
    }
    default:
      break;
  }
  m_pOldDelegate->OnProcessEvent(pEvent);
}
void CXFA_FFListBox::OnDrawWidget(CFX_Graphics* pGraphics,
                                  const CFX_Matrix* pMatrix) {
  m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
}

CXFA_FFComboBox::CXFA_FFComboBox(CXFA_WidgetAcc* pDataAcc)
    : CXFA_FFField(pDataAcc), m_pOldDelegate(nullptr) {}

CXFA_FFComboBox::~CXFA_FFComboBox() {}

CFX_RectF CXFA_FFComboBox::GetBBox(uint32_t dwStatus, bool bDrawFocus) {
  if (bDrawFocus)
    return CFX_RectF();
  return CXFA_FFWidget::GetBBox(dwStatus);
}

bool CXFA_FFComboBox::PtInActiveRect(const CFX_PointF& point) {
  auto pComboBox = static_cast<CFWL_ComboBox*>(m_pNormalWidget);
  return pComboBox && pComboBox->GetBBox().Contains(point);
}

bool CXFA_FFComboBox::LoadWidget() {
  CFWL_ComboBox* pComboBox = new CFWL_ComboBox(GetFWLApp());
  m_pNormalWidget = (CFWL_Widget*)pComboBox;
  m_pNormalWidget->SetLayoutItem(this);

  CFWL_NoteDriver* pNoteDriver =
      m_pNormalWidget->GetOwnerApp()->GetNoteDriver();
  pNoteDriver->RegisterEventTarget(m_pNormalWidget, m_pNormalWidget);

  m_pOldDelegate = m_pNormalWidget->GetDelegate();
  m_pNormalWidget->SetDelegate(this);
  m_pNormalWidget->LockUpdate();

  std::vector<CFX_WideString> wsLabelArray;
  m_pDataAcc->GetChoiceListItems(wsLabelArray, false);
  int32_t iItems = pdfium::CollectionSize<int32_t>(wsLabelArray);
  for (int32_t i = 0; i < iItems; i++) {
    pComboBox->AddString(wsLabelArray[i].AsStringC());
  }
  CFX_ArrayTemplate<int32_t> iSelArray;
  m_pDataAcc->GetSelectedItems(iSelArray);
  int32_t iSelCount = iSelArray.GetSize();
  if (iSelCount > 0) {
    pComboBox->SetCurSel(iSelArray[0]);
  } else {
    CFX_WideString wsText;
    m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw);
    pComboBox->SetEditText(wsText);
  }
  UpdateWidgetProperty();
  m_pNormalWidget->UnlockUpdate();
  return CXFA_FFField::LoadWidget();
}
void CXFA_FFComboBox::UpdateWidgetProperty() {
  CFWL_ComboBox* pComboBox = (CFWL_ComboBox*)m_pNormalWidget;
  if (!pComboBox) {
    return;
  }
  uint32_t dwExtendedStyle = 0;
  uint32_t dwEditStyles =
      FWL_STYLEEXT_EDT_ReadOnly | FWL_STYLEEXT_EDT_LastLineHeight;
  dwExtendedStyle |= UpdateUIProperty();
  if (m_pDataAcc->IsChoiceListAllowTextEntry()) {
    dwEditStyles &= ~FWL_STYLEEXT_EDT_ReadOnly;
    dwExtendedStyle |= FWL_STYLEEXT_CMB_DropDown;
  }
  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open ||
      !m_pDataAcc->GetDoc()->GetXFADoc()->IsInteractive()) {
    dwEditStyles |= FWL_STYLEEXT_EDT_ReadOnly;
    dwExtendedStyle |= FWL_STYLEEXT_CMB_ReadOnly;
  }
  dwExtendedStyle |= GetAlignment();
  m_pNormalWidget->ModifyStylesEx(dwExtendedStyle, 0xFFFFFFFF);
  if (m_pDataAcc->GetHorizontalScrollPolicy() != XFA_ATTRIBUTEENUM_Off) {
    dwEditStyles |= FWL_STYLEEXT_EDT_AutoHScroll;
  }
  pComboBox->EditModifyStylesEx(dwEditStyles, 0xFFFFFFFF);
}

bool CXFA_FFComboBox::OnRButtonUp(uint32_t dwFlags, const CFX_PointF& point) {
  if (!CXFA_FFField::OnRButtonUp(dwFlags, point))
    return false;

  GetDoc()->GetDocEnvironment()->PopupMenu(this, point);
  return true;
}

bool CXFA_FFComboBox::OnKillFocus(CXFA_FFWidget* pNewWidget) {
  bool flag = ProcessCommittedData();
  if (!flag) {
    UpdateFWLData();
  }
  CXFA_FFField::OnKillFocus(pNewWidget);
  return true;
}
void CXFA_FFComboBox::OpenDropDownList() {
  ((CFWL_ComboBox*)m_pNormalWidget)->OpenDropDownList(true);
}
bool CXFA_FFComboBox::CommitData() {
  return m_pDataAcc->SetValue(m_wsNewValue, XFA_VALUEPICTURE_Raw);
}
bool CXFA_FFComboBox::IsDataChanged() {
  CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget);
  CFX_WideString wsText = pFWLcombobox->GetEditText();
  int32_t iCursel = pFWLcombobox->GetCurSel();
  if (iCursel >= 0) {
    CFX_WideString wsSel = pFWLcombobox->GetTextByIndex(iCursel);
    if (wsSel == wsText)
      m_pDataAcc->GetChoiceListItem(wsText, iCursel, true);
  }

  CFX_WideString wsOldValue;
  m_pDataAcc->GetValue(wsOldValue, XFA_VALUEPICTURE_Raw);
  if (wsOldValue != wsText) {
    m_wsNewValue = wsText;
    return true;
  }
  return false;
}
void CXFA_FFComboBox::FWLEventSelChange(CXFA_EventParam* pParam) {
  pParam->m_eType = XFA_EVENT_Change;
  pParam->m_pTarget = m_pDataAcc;
  CFWL_ComboBox* pFWLcombobox = ((CFWL_ComboBox*)m_pNormalWidget);
  pParam->m_wsNewText = pFWLcombobox->GetEditText();
  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_Change, pParam);
}
uint32_t CXFA_FFComboBox::GetAlignment() {
  uint32_t dwExtendedStyle = 0;
  if (CXFA_Para para = m_pDataAcc->GetPara()) {
    int32_t iHorz = para.GetHorizontalAlign();
    switch (iHorz) {
      case XFA_ATTRIBUTEENUM_Center:
        dwExtendedStyle |=
            FWL_STYLEEXT_CMB_EditHCenter | FWL_STYLEEXT_CMB_ListItemCenterAlign;
        break;
      case XFA_ATTRIBUTEENUM_Justify:
        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditJustified;
        break;
      case XFA_ATTRIBUTEENUM_JustifyAll:
        break;
      case XFA_ATTRIBUTEENUM_Radix:
        break;
      case XFA_ATTRIBUTEENUM_Right:
        break;
      default:
        dwExtendedStyle |=
            FWL_STYLEEXT_CMB_EditHNear | FWL_STYLEEXT_CMB_ListItemLeftAlign;
        break;
    }
    int32_t iVert = para.GetVerticalAlign();
    switch (iVert) {
      case XFA_ATTRIBUTEENUM_Middle:
        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVCenter;
        break;
      case XFA_ATTRIBUTEENUM_Bottom:
        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVFar;
        break;
      default:
        dwExtendedStyle |= FWL_STYLEEXT_CMB_EditVNear;
        break;
    }
  }
  return dwExtendedStyle;
}
bool CXFA_FFComboBox::UpdateFWLData() {
  if (!m_pNormalWidget) {
    return false;
  }
  CFX_ArrayTemplate<int32_t> iSelArray;
  m_pDataAcc->GetSelectedItems(iSelArray);
  int32_t iSelCount = iSelArray.GetSize();
  if (iSelCount > 0) {
    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(iSelArray[0]);
  } else {
    CFX_WideString wsText;
    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1);
    m_pDataAcc->GetValue(wsText, XFA_VALUEPICTURE_Raw);
    ((CFWL_ComboBox*)m_pNormalWidget)->SetEditText(wsText);
  }
  m_pNormalWidget->Update();
  return true;
}
bool CXFA_FFComboBox::CanUndo() {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanUndo();
}
bool CXFA_FFComboBox::CanRedo() {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanRedo();
}
bool CXFA_FFComboBox::Undo() {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditUndo();
}
bool CXFA_FFComboBox::Redo() {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditRedo();
}
bool CXFA_FFComboBox::CanCopy() {
  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCopy();
}
bool CXFA_FFComboBox::CanCut() {
  if (m_pDataAcc->GetAccess() != XFA_ATTRIBUTEENUM_Open) {
    return false;
  }
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditCanCut();
}
bool CXFA_FFComboBox::CanPaste() {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         (m_pDataAcc->GetAccess() == XFA_ATTRIBUTEENUM_Open);
}
bool CXFA_FFComboBox::CanSelectAll() {
  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCanSelectAll();
}
bool CXFA_FFComboBox::Copy(CFX_WideString& wsCopy) {
  return ((CFWL_ComboBox*)m_pNormalWidget)->EditCopy(wsCopy);
}
bool CXFA_FFComboBox::Cut(CFX_WideString& wsCut) {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditCut(wsCut);
}
bool CXFA_FFComboBox::Paste(const CFX_WideString& wsPaste) {
  return m_pDataAcc->IsChoiceListAllowTextEntry() &&
         ((CFWL_ComboBox*)m_pNormalWidget)->EditPaste(wsPaste);
}
void CXFA_FFComboBox::SelectAll() {
  ((CFWL_ComboBox*)m_pNormalWidget)->EditSelectAll();
}
void CXFA_FFComboBox::Delete() {
  ((CFWL_ComboBox*)m_pNormalWidget)->EditDelete();
}
void CXFA_FFComboBox::DeSelect() {
  ((CFWL_ComboBox*)m_pNormalWidget)->EditDeSelect();
}
void CXFA_FFComboBox::SetItemState(int32_t nIndex, bool bSelected) {
  if (bSelected) {
    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(nIndex);
  } else {
    ((CFWL_ComboBox*)m_pNormalWidget)->SetCurSel(-1);
  }
  m_pNormalWidget->Update();
  AddInvalidateRect();
}
void CXFA_FFComboBox::InsertItem(const CFX_WideStringC& wsLabel,
                                 int32_t nIndex) {
  ((CFWL_ComboBox*)m_pNormalWidget)->AddString(wsLabel);
  m_pNormalWidget->Update();
  AddInvalidateRect();
}
void CXFA_FFComboBox::DeleteItem(int32_t nIndex) {
  if (nIndex < 0) {
    ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAll();
  } else {
    ((CFWL_ComboBox*)m_pNormalWidget)->RemoveAt(nIndex);
  }
  m_pNormalWidget->Update();
  AddInvalidateRect();
}
void CXFA_FFComboBox::OnTextChanged(CFWL_Widget* pWidget,
                                    const CFX_WideString& wsChanged) {
  CXFA_EventParam eParam;
  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
  eParam.m_wsChange = wsChanged;
  FWLEventSelChange(&eParam);
}
void CXFA_FFComboBox::OnSelectChanged(CFWL_Widget* pWidget, bool bLButtonUp) {
  CXFA_EventParam eParam;
  m_pDataAcc->GetValue(eParam.m_wsPrevText, XFA_VALUEPICTURE_Raw);
  FWLEventSelChange(&eParam);
  if (m_pDataAcc->GetChoiceListCommitOn() == XFA_ATTRIBUTEENUM_Select &&
      bLButtonUp) {
    m_pDocView->SetFocusWidgetAcc(nullptr);
  }
}
void CXFA_FFComboBox::OnPreOpen(CFWL_Widget* pWidget) {
  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_PreOpen;
  eParam.m_pTarget = m_pDataAcc;
  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PreOpen, &eParam);
}
void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) {
  CXFA_EventParam eParam;
  eParam.m_eType = XFA_EVENT_PostOpen;
  eParam.m_pTarget = m_pDataAcc;
  m_pDataAcc->ProcessEvent(XFA_ATTRIBUTEENUM_PostOpen, &eParam);
}

void CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) {
  m_pOldDelegate->OnProcessMessage(pMessage);
}

void CXFA_FFComboBox::OnProcessEvent(CFWL_Event* pEvent) {
  CXFA_FFField::OnProcessEvent(pEvent);
  switch (pEvent->GetType()) {
    case CFWL_Event::Type::SelectChanged: {
      CFWL_EventSelectChanged* postEvent =
          static_cast<CFWL_EventSelectChanged*>(pEvent);
      OnSelectChanged(m_pNormalWidget, postEvent->bLButtonUp);
      break;
    }
    case CFWL_Event::Type::EditChanged: {
      CFX_WideString wsChanged;
      OnTextChanged(m_pNormalWidget, wsChanged);
      break;
    }
    case CFWL_Event::Type::PreDropDown: {
      OnPreOpen(m_pNormalWidget);
      break;
    }
    case CFWL_Event::Type::PostDropDown: {
      OnPostOpen(m_pNormalWidget);
      break;
    }
    default:
      break;
  }
  m_pOldDelegate->OnProcessEvent(pEvent);
}

void CXFA_FFComboBox::OnDrawWidget(CFX_Graphics* pGraphics,
                                   const CFX_Matrix* pMatrix) {
  m_pOldDelegate->OnDrawWidget(pGraphics, pMatrix);
}