1 // Copyright 2014 PDFium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7 #include "xfa/src/foxitlib.h" 8 #include "xfa/src/fwl/src/core/include/fwl_threadimp.h" 9 #include "xfa/src/fwl/src/core/include/fwl_appimp.h" 10 #include "xfa/src/fwl/src/core/include/fwl_targetimp.h" 11 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h" 12 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h" 13 #include "xfa/src/fwl/src/core/include/fwl_panelimp.h" 14 #include "xfa/src/fwl/src/core/include/fwl_formimp.h" 15 #include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h" 16 #include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h" 17 #include "xfa/src/fwl/src/basewidget/include/fwl_editimp.h" 18 #include "xfa/src/fwl/src/basewidget/include/fwl_listboximp.h" 19 #include "xfa/src/fwl/src/basewidget/include/fwl_formproxyimp.h" 20 #include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h" 21 22 // static 23 IFWL_ComboBox* IFWL_ComboBox::Create( 24 const CFWL_WidgetImpProperties& properties) { 25 IFWL_ComboBox* pComboBox = new IFWL_ComboBox; 26 CFWL_ComboBoxImp* pComboBoxImpl = new CFWL_ComboBoxImp(properties, nullptr); 27 pComboBox->SetImpl(pComboBoxImpl); 28 pComboBoxImpl->SetInterface(pComboBox); 29 return pComboBox; 30 } 31 IFWL_ComboBox::IFWL_ComboBox() {} 32 int32_t IFWL_ComboBox::GetCurSel() { 33 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetCurSel(); 34 } 35 FWL_ERR IFWL_ComboBox::SetCurSel(int32_t iSel) { 36 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetCurSel(iSel); 37 } 38 FWL_ERR IFWL_ComboBox::SetEditText(const CFX_WideString& wsText) { 39 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditText(wsText); 40 } 41 int32_t IFWL_ComboBox::GetEditTextLength() const { 42 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditTextLength(); 43 } 44 FWL_ERR IFWL_ComboBox::GetEditText(CFX_WideString& wsText, 45 int32_t nStart, 46 int32_t nCount) const { 47 return static_cast<CFWL_ComboBoxImp*>(GetImpl()) 48 ->GetEditText(wsText, nStart, nCount); 49 } 50 FWL_ERR IFWL_ComboBox::SetEditSelRange(int32_t nStart, int32_t nCount) { 51 return static_cast<CFWL_ComboBoxImp*>(GetImpl()) 52 ->SetEditSelRange(nStart, nCount); 53 } 54 int32_t IFWL_ComboBox::GetEditSelRange(int32_t nIndex, int32_t& nStart) { 55 return static_cast<CFWL_ComboBoxImp*>(GetImpl()) 56 ->GetEditSelRange(nIndex, nStart); 57 } 58 int32_t IFWL_ComboBox::GetEditLimit() { 59 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetEditLimit(); 60 } 61 FWL_ERR IFWL_ComboBox::SetEditLimit(int32_t nLimit) { 62 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->SetEditLimit(nLimit); 63 } 64 FWL_ERR IFWL_ComboBox::EditDoClipboard(int32_t iCmd) { 65 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDoClipboard(iCmd); 66 } 67 FX_BOOL IFWL_ComboBox::EditRedo(const CFX_ByteStringC& bsRecord) { 68 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(bsRecord); 69 } 70 FX_BOOL IFWL_ComboBox::EditUndo(const CFX_ByteStringC& bsRecord) { 71 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(bsRecord); 72 } 73 IFWL_ListBox* IFWL_ComboBox::GetListBoxt() { 74 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetListBoxt(); 75 } 76 FX_BOOL IFWL_ComboBox::AfterFocusShowDropList() { 77 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->AfterFocusShowDropList(); 78 } 79 FX_ERR IFWL_ComboBox::OpenDropDownList(FX_BOOL bActivate) { 80 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->OpenDropDownList(bActivate); 81 } 82 FX_BOOL IFWL_ComboBox::EditCanUndo() { 83 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanUndo(); 84 } 85 FX_BOOL IFWL_ComboBox::EditCanRedo() { 86 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanRedo(); 87 } 88 FX_BOOL IFWL_ComboBox::EditUndo() { 89 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditUndo(); 90 } 91 FX_BOOL IFWL_ComboBox::EditRedo() { 92 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditRedo(); 93 } 94 FX_BOOL IFWL_ComboBox::EditCanCopy() { 95 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCopy(); 96 } 97 FX_BOOL IFWL_ComboBox::EditCanCut() { 98 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanCut(); 99 } 100 FX_BOOL IFWL_ComboBox::EditCanSelectAll() { 101 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCanSelectAll(); 102 } 103 FX_BOOL IFWL_ComboBox::EditCopy(CFX_WideString& wsCopy) { 104 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCopy(wsCopy); 105 } 106 FX_BOOL IFWL_ComboBox::EditCut(CFX_WideString& wsCut) { 107 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditCut(wsCut); 108 } 109 FX_BOOL IFWL_ComboBox::EditPaste(const CFX_WideString& wsPaste) { 110 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditPaste(wsPaste); 111 } 112 FX_BOOL IFWL_ComboBox::EditSelectAll() { 113 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditSelectAll(); 114 } 115 FX_BOOL IFWL_ComboBox::EditDelete() { 116 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDelete(); 117 } 118 FX_BOOL IFWL_ComboBox::EditDeSelect() { 119 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->EditDeSelect(); 120 } 121 FWL_ERR IFWL_ComboBox::GetBBox(CFX_RectF& rect) { 122 return static_cast<CFWL_ComboBoxImp*>(GetImpl())->GetBBox(rect); 123 } 124 FWL_ERR IFWL_ComboBox::EditModifyStylesEx(FX_DWORD dwStylesExAdded, 125 FX_DWORD dwStylesExRemoved) { 126 return static_cast<CFWL_ComboBoxImp*>(GetImpl()) 127 ->EditModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); 128 } 129 130 CFWL_ComboEditImp::CFWL_ComboEditImp(const CFWL_WidgetImpProperties& properties, 131 IFWL_Widget* pOuter) 132 : CFWL_EditImp(properties, pOuter) { 133 m_pOuter = static_cast<CFWL_ComboBoxImp*>(pOuter->GetImpl()); 134 } 135 136 CFWL_ComboEditImpDelegate::CFWL_ComboEditImpDelegate(CFWL_ComboEditImp* pOwner) 137 : CFWL_EditImpDelegate(pOwner), m_pOwner(pOwner) { 138 } 139 int32_t CFWL_ComboEditImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { 140 if (!pMessage) 141 return 0; 142 FX_DWORD dwMsgCode = pMessage->GetClassID(); 143 FX_BOOL backDefault = TRUE; 144 switch (dwMsgCode) { 145 case FWL_MSGHASH_SetFocus: 146 case FWL_MSGHASH_KillFocus: { 147 if (dwMsgCode == FWL_MSGHASH_SetFocus) { 148 m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; 149 } else { 150 m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; 151 } 152 backDefault = FALSE; 153 break; 154 } 155 case FWL_MSGHASH_Mouse: { 156 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 157 if ((pMsg->m_dwCmd == FWL_MSGMOUSECMD_LButtonDown) && 158 ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0)) { 159 m_pOwner->SetSelected(); 160 m_pOwner->SetComboBoxFocus(TRUE); 161 } 162 break; 163 } 164 default: {} 165 } 166 if (!backDefault) { 167 return 1; 168 } 169 return CFWL_EditImpDelegate::OnProcessMessage(pMessage); 170 } 171 void CFWL_ComboEditImp::ClearSelected() { 172 ClearSelections(); 173 Repaint(&m_rtClient); 174 } 175 void CFWL_ComboEditImp::SetSelected() { 176 FlagFocus(TRUE); 177 EndCaret(); 178 AddSelRange(0); 179 } 180 void CFWL_ComboEditImp::EndCaret() { 181 m_pEdtEngine->MoveCaretPos(MC_End); 182 } 183 void CFWL_ComboEditImp::FlagFocus(FX_BOOL bSet) { 184 if (bSet) { 185 m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; 186 } else { 187 m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; 188 ShowCaret(FALSE); 189 } 190 }; 191 void CFWL_ComboEditImp::SetComboBoxFocus(FX_BOOL bSet) { 192 m_pOuter->SetFocus(bSet); 193 } 194 CFWL_ComboListImp::CFWL_ComboListImp(const CFWL_WidgetImpProperties& properties, 195 IFWL_Widget* pOuter) 196 : CFWL_ListBoxImp(properties, pOuter), m_bNotifyOwner(TRUE) { 197 FXSYS_assert(pOuter != NULL); 198 } 199 FWL_ERR CFWL_ComboListImp::Initialize() { 200 if (CFWL_ListBoxImp::Initialize() != FWL_ERR_Succeeded) 201 return FWL_ERR_Indefinite; 202 delete m_pDelegate; 203 m_pDelegate = new CFWL_ComboListImpDelegate(this); 204 return FWL_ERR_Succeeded; 205 } 206 FWL_ERR CFWL_ComboListImp::Finalize() { 207 delete m_pDelegate; 208 m_pDelegate = nullptr; 209 return CFWL_ListBoxImp::Finalize(); 210 } 211 int32_t CFWL_ComboListImp::MatchItem(const CFX_WideString& wsMatch) { 212 if (wsMatch.IsEmpty()) { 213 return -1; 214 } 215 if (!m_pProperties->m_pDataProvider) 216 return -1; 217 IFWL_ListBoxDP* pData = 218 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 219 int32_t iCount = pData->CountItems(m_pInterface); 220 for (int32_t i = 0; i < iCount; i++) { 221 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 222 CFX_WideString wsText; 223 pData->GetItemText(m_pInterface, hItem, wsText); 224 FX_STRSIZE pos = wsText.Find(wsMatch.c_str()); 225 if (!pos) { 226 return i; 227 } 228 } 229 return -1; 230 } 231 void CFWL_ComboListImp::ChangeSelected(int32_t iSel) { 232 if (!m_pProperties->m_pDataProvider) 233 return; 234 IFWL_ListBoxDP* pData = 235 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 236 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel); 237 CFX_RectF rtInvalidate; 238 rtInvalidate.Reset(); 239 FWL_HLISTITEM hOld = GetSelItem(0); 240 int32_t iOld = pData->GetItemIndex(m_pInterface, hOld); 241 if (iOld == iSel) { 242 return; 243 } else if (iOld > -1) { 244 GetItemRect(iOld, rtInvalidate); 245 SetSelItem(hOld, FALSE); 246 } 247 if (hItem) { 248 CFX_RectF rect; 249 GetItemRect(iSel, rect); 250 rtInvalidate.Union(rect); 251 FWL_HLISTITEM hSel = pData->GetItem(m_pInterface, iSel); 252 SetSelItem(hSel, TRUE); 253 } 254 if (!rtInvalidate.IsEmpty()) { 255 Repaint(&rtInvalidate); 256 } 257 } 258 int32_t CFWL_ComboListImp::CountItems() { 259 IFWL_ListBoxDP* pData = 260 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 261 return pData ? pData->CountItems(m_pInterface) : 0; 262 } 263 void CFWL_ComboListImp::GetItemRect(int32_t nIndex, CFX_RectF& rtItem) { 264 IFWL_ListBoxDP* pData = 265 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 266 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, nIndex); 267 pData->GetItemRect(m_pInterface, hItem, rtItem); 268 } 269 void CFWL_ComboListImp::ClientToOuter(FX_FLOAT& fx, FX_FLOAT& fy) { 270 fx += m_pProperties->m_rtWidget.left, fy += m_pProperties->m_rtWidget.top; 271 IFWL_Widget* pOwner = GetOwner(); 272 if (!pOwner) 273 return; 274 pOwner->TransformTo(m_pOuter, fx, fy); 275 } 276 void CFWL_ComboListImp::SetFocus(FX_BOOL bSet) { 277 CFWL_WidgetImp::SetFocus(bSet); 278 } 279 CFWL_ComboListImpDelegate::CFWL_ComboListImpDelegate(CFWL_ComboListImp* pOwner) 280 : CFWL_ListBoxImpDelegate(pOwner), m_pOwner(pOwner) { 281 } 282 int32_t CFWL_ComboListImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { 283 if (!pMessage) 284 return 0; 285 FX_DWORD dwHashCode = pMessage->GetClassID(); 286 FX_BOOL backDefault = TRUE; 287 if (dwHashCode == FWL_MSGHASH_SetFocus || 288 dwHashCode == FWL_MSGHASH_KillFocus) { 289 OnDropListFocusChanged(pMessage, dwHashCode == FWL_MSGHASH_SetFocus); 290 } else if (dwHashCode == FWL_MSGHASH_Mouse) { 291 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 292 if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { 293 CFX_RectF rect; 294 m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); 295 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { 296 pMsg->m_fx -= rect.left; 297 pMsg->m_fy -= rect.top; 298 IFWL_WidgetDelegate* pDelegate = 299 m_pOwner->m_pVertScrollBar->SetDelegate(NULL); 300 return pDelegate->OnProcessMessage(pMsg); 301 } 302 } 303 FX_DWORD dwCmd = pMsg->m_dwCmd; 304 switch (dwCmd) { 305 case FWL_MSGMOUSECMD_MouseMove: { 306 backDefault = FALSE; 307 OnDropListMouseMove(pMsg); 308 break; 309 } 310 case FWL_MSGMOUSECMD_LButtonDown: { 311 backDefault = FALSE; 312 OnDropListLButtonDown(pMsg); 313 break; 314 } 315 case FWL_MSGMOUSECMD_LButtonUp: { 316 backDefault = FALSE; 317 OnDropListLButtonUp(pMsg); 318 break; 319 } 320 default: {} 321 } 322 } else if (dwHashCode == FWL_MSGHASH_Key) { 323 backDefault = !OnDropListKey(static_cast<CFWL_MsgKey*>(pMessage)); 324 } 325 if (!backDefault) { 326 return 1; 327 } 328 return CFWL_ListBoxImpDelegate::OnProcessMessage(pMessage); 329 } 330 void CFWL_ComboListImpDelegate::OnDropListFocusChanged(CFWL_Message* pMsg, 331 FX_BOOL bSet) { 332 if (!bSet) { 333 CFWL_MsgKillFocus* pKill = static_cast<CFWL_MsgKillFocus*>(pMsg); 334 CFWL_ComboBoxImp* pOuter = 335 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 336 if (pKill->m_pSetFocus == m_pOwner->m_pOuter || 337 pKill->m_pSetFocus == pOuter->m_pEdit.get()) { 338 pOuter->ShowDropList(FALSE); 339 } 340 } 341 } 342 int32_t CFWL_ComboListImpDelegate::OnDropListMouseMove(CFWL_MsgMouse* pMsg) { 343 if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { 344 if (m_pOwner->m_bNotifyOwner) { 345 m_pOwner->m_bNotifyOwner = FALSE; 346 } 347 if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { 348 CFX_RectF rect; 349 m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); 350 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { 351 return 1; 352 } 353 } 354 FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); 355 if (hItem) { 356 if (!m_pOwner->m_pProperties->m_pDataProvider) 357 return 0; 358 IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( 359 m_pOwner->m_pProperties->m_pDataProvider); 360 int32_t iSel = pData->GetItemIndex(m_pOwner->m_pInterface, hItem); 361 CFWL_EvtCmbHoverChanged event; 362 event.m_pSrcTarget = m_pOwner->m_pOuter; 363 event.m_iCurHover = iSel; 364 m_pOwner->DispatchEvent(&event); 365 m_pOwner->ChangeSelected(iSel); 366 } 367 } else if (m_pOwner->m_bNotifyOwner) { 368 m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy); 369 CFWL_ComboBoxImp* pOuter = 370 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 371 pOuter->m_pDelegate->OnProcessMessage(pMsg); 372 } 373 return 1; 374 } 375 int32_t CFWL_ComboListImpDelegate::OnDropListLButtonDown(CFWL_MsgMouse* pMsg) { 376 if (m_pOwner->m_rtClient.Contains(pMsg->m_fx, pMsg->m_fy)) { 377 return 0; 378 } 379 CFWL_ComboBoxImp* pOuter = 380 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 381 pOuter->ShowDropList(FALSE); 382 return 1; 383 } 384 int32_t CFWL_ComboListImpDelegate::OnDropListLButtonUp(CFWL_MsgMouse* pMsg) { 385 CFWL_ComboBoxImp* pOuter = 386 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 387 if (m_pOwner->m_bNotifyOwner) { 388 m_pOwner->ClientToOuter(pMsg->m_fx, pMsg->m_fy); 389 pOuter->m_pDelegate->OnProcessMessage(pMsg); 390 } else { 391 if (m_pOwner->IsShowScrollBar(TRUE) && m_pOwner->m_pVertScrollBar) { 392 CFX_RectF rect; 393 m_pOwner->m_pVertScrollBar->GetWidgetRect(rect); 394 if (rect.Contains(pMsg->m_fx, pMsg->m_fy)) { 395 return 1; 396 } 397 } 398 pOuter->ShowDropList(FALSE); 399 FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); 400 if (hItem) { 401 pOuter->ProcessSelChanged(TRUE); 402 } 403 } 404 return 1; 405 } 406 int32_t CFWL_ComboListImpDelegate::OnDropListKey(CFWL_MsgKey* pKey) { 407 CFWL_ComboBoxImp* pOuter = 408 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 409 FX_BOOL bPropagate = FALSE; 410 if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) { 411 FX_DWORD dwKeyCode = pKey->m_dwKeyCode; 412 switch (dwKeyCode) { 413 case FWL_VKEY_Return: 414 case FWL_VKEY_Escape: { 415 pOuter->ShowDropList(FALSE); 416 return 1; 417 } 418 case FWL_VKEY_Up: 419 case FWL_VKEY_Down: { 420 OnDropListKeyDown(pKey); 421 pOuter->SetDelegate(nullptr); 422 pOuter->ProcessSelChanged(FALSE); 423 return 1; 424 } 425 default: { bPropagate = TRUE; } 426 } 427 } else if (pKey->m_dwCmd == FWL_MSGKEYCMD_Char) { 428 bPropagate = TRUE; 429 } 430 if (bPropagate) { 431 pKey->m_pDstTarget = m_pOwner->m_pOuter; 432 pOuter->m_pDelegate->OnProcessMessage(pKey); 433 return 1; 434 } 435 return 0; 436 } 437 void CFWL_ComboListImpDelegate::OnDropListKeyDown(CFWL_MsgKey* pKey) { 438 FX_DWORD dwKeyCode = pKey->m_dwKeyCode; 439 switch (dwKeyCode) { 440 case FWL_VKEY_Up: 441 case FWL_VKEY_Down: 442 case FWL_VKEY_Home: 443 case FWL_VKEY_End: { 444 CFWL_ComboBoxImp* pOuter = 445 static_cast<CFWL_ComboBoxImp*>(m_pOwner->m_pOuter->GetImpl()); 446 IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( 447 m_pOwner->m_pProperties->m_pDataProvider); 448 FWL_HLISTITEM hItem = 449 pData->GetItem(m_pOwner->m_pInterface, pOuter->m_iCurSel); 450 hItem = m_pOwner->GetItem(hItem, dwKeyCode); 451 if (!hItem) { 452 break; 453 } 454 m_pOwner->SetSelection(hItem, hItem, TRUE); 455 m_pOwner->ScrollToVisible(hItem); 456 CFX_RectF rtInvalidate; 457 rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width, 458 m_pOwner->m_pProperties->m_rtWidget.height); 459 m_pOwner->Repaint(&rtInvalidate); 460 break; 461 } 462 default: {} 463 } 464 } 465 CFWL_ComboBoxImp::CFWL_ComboBoxImp(const CFWL_WidgetImpProperties& properties, 466 IFWL_Widget* pOuter) 467 : CFWL_WidgetImp(properties, pOuter), 468 m_pForm(NULL), 469 m_bLButtonDown(FALSE), 470 m_iCurSel(-1), 471 m_iBtnState(FWL_PARTSTATE_CMB_Normal), 472 m_fComboFormHandler(0), 473 m_bNeedShowList(FALSE) { 474 m_rtClient.Reset(); 475 m_rtBtn.Reset(); 476 m_rtHandler.Reset(); 477 } 478 CFWL_ComboBoxImp::~CFWL_ComboBoxImp() { 479 } 480 FWL_ERR CFWL_ComboBoxImp::GetClassName(CFX_WideString& wsClass) const { 481 wsClass = FWL_CLASS_ComboBox; 482 return FWL_ERR_Succeeded; 483 } 484 FX_DWORD CFWL_ComboBoxImp::GetClassID() const { 485 return FWL_CLASSHASH_ComboBox; 486 } 487 FWL_ERR CFWL_ComboBoxImp::Initialize() { 488 if (m_pWidgetMgr->IsFormDisabled()) { 489 return DisForm_Initialize(); 490 } 491 if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) 492 return FWL_WGTSTATE_Invisible; // Probably a bug; not a FWL_ERR_ value. 493 m_pDelegate = new CFWL_ComboBoxImpDelegate(this); 494 CFWL_WidgetImpProperties prop; 495 prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; 496 prop.m_dwStyles |= FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; 497 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListItemIconText) { 498 prop.m_dwStyleExes |= FWL_STYLEEXT_LTB_Icon; 499 } 500 prop.m_pDataProvider = m_pProperties->m_pDataProvider; 501 m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface)); 502 m_pListBox->Initialize(); 503 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown) && !m_pEdit) { 504 CFWL_WidgetImpProperties prop2; 505 m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop2, m_pInterface)); 506 m_pEdit->Initialize(); 507 static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); 508 } 509 if (m_pEdit) { 510 m_pEdit->SetParent(m_pInterface); 511 } 512 SetStates(m_pProperties->m_dwStates); 513 return FWL_ERR_Succeeded; 514 } 515 FWL_ERR CFWL_ComboBoxImp::Finalize() { 516 if (m_pEdit) { 517 m_pEdit->Finalize(); 518 } 519 m_pListBox->Finalize(); 520 delete m_pDelegate; 521 m_pDelegate = nullptr; 522 return CFWL_WidgetImp::Finalize(); 523 } 524 FWL_ERR CFWL_ComboBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { 525 if (bAutoSize) { 526 rect.Reset(); 527 FX_BOOL bIsDropDown = IsDropDownStyle(); 528 if (bIsDropDown && m_pEdit) { 529 m_pEdit->GetWidgetRect(rect, TRUE); 530 } else { 531 rect.width = 100; 532 rect.height = 16; 533 } 534 if (!m_pProperties->m_pThemeProvider) { 535 ReSetTheme(); 536 } 537 FX_FLOAT* pFWidth = static_cast<FX_FLOAT*>( 538 GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); 539 if (!pFWidth) 540 return FWL_ERR_Indefinite; 541 rect.Inflate(0, 0, *pFWidth, 0); 542 CFWL_WidgetImp::GetWidgetRect(rect, TRUE); 543 } else { 544 rect = m_pProperties->m_rtWidget; 545 } 546 return FWL_ERR_Succeeded; 547 } 548 FWL_ERR CFWL_ComboBoxImp::ModifyStylesEx(FX_DWORD dwStylesExAdded, 549 FX_DWORD dwStylesExRemoved) { 550 if (m_pWidgetMgr->IsFormDisabled()) { 551 return DisForm_ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); 552 } 553 FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown; 554 FX_BOOL bRemoveDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown; 555 if (bAddDropDown && !m_pEdit) { 556 CFWL_WidgetImpProperties prop; 557 m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, nullptr)); 558 m_pEdit->Initialize(); 559 static_cast<CFWL_EditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); 560 m_pEdit->SetParent(m_pInterface); 561 } else if (bRemoveDropDown && m_pEdit) { 562 m_pEdit->SetStates(FWL_WGTSTATE_Invisible, TRUE); 563 } 564 return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); 565 } 566 FWL_ERR CFWL_ComboBoxImp::Update() { 567 if (m_pWidgetMgr->IsFormDisabled()) { 568 return DisForm_Update(); 569 } 570 if (IsLocked()) { 571 return FWL_ERR_Indefinite; 572 } 573 ReSetTheme(); 574 FX_BOOL bDropDown = IsDropDownStyle(); 575 if (bDropDown && m_pEdit) { 576 ReSetEditAlignment(); 577 } 578 if (m_pProperties->m_pThemeProvider == NULL) { 579 m_pProperties->m_pThemeProvider = GetAvailableTheme(); 580 } 581 Layout(); 582 CFWL_ThemePart part; 583 part.m_pWidget = m_pInterface; 584 m_fComboFormHandler = 585 *static_cast<FX_FLOAT*>(m_pProperties->m_pThemeProvider->GetCapacity( 586 &part, FWL_WGTCAPACITY_CMB_ComboFormHandler)); 587 return FWL_ERR_Succeeded; 588 } 589 FX_DWORD CFWL_ComboBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { 590 if (m_pWidgetMgr->IsFormDisabled()) { 591 return DisForm_HitTest(fx, fy); 592 } 593 return CFWL_WidgetImp::HitTest(fx, fy); 594 } 595 FWL_ERR CFWL_ComboBoxImp::DrawWidget(CFX_Graphics* pGraphics, 596 const CFX_Matrix* pMatrix) { 597 if (m_pWidgetMgr->IsFormDisabled()) { 598 return DisForm_DrawWidget(pGraphics, pMatrix); 599 } 600 if (!pGraphics) 601 return FWL_ERR_Indefinite; 602 if (!m_pProperties->m_pThemeProvider) 603 return FWL_ERR_Indefinite; 604 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; 605 FX_BOOL bIsDropDown = IsDropDownStyle(); 606 if (HasBorder()) { 607 DrawBorder(pGraphics, FWL_PART_CMB_Border, pTheme, pMatrix); 608 } 609 if (HasEdge()) { 610 DrawEdge(pGraphics, FWL_PART_CMB_Edge, pTheme, pMatrix); 611 } 612 if (!bIsDropDown) { 613 CFX_RectF rtTextBk(m_rtClient); 614 rtTextBk.width -= m_rtBtn.width; 615 CFWL_ThemeBackground param; 616 param.m_pWidget = m_pInterface; 617 param.m_iPart = FWL_PART_CMB_Background; 618 param.m_pGraphics = pGraphics; 619 if (pMatrix) { 620 param.m_matrix.Concat(*pMatrix); 621 } 622 param.m_rtPart = rtTextBk; 623 if (m_iCurSel >= 0) { 624 IFWL_ListBoxDP* pData = static_cast<IFWL_ListBoxDP*>( 625 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 626 ->m_pProperties->m_pDataProvider); 627 void* p = pData->GetItemData(m_pListBox.get(), 628 pData->GetItem(m_pListBox.get(), m_iCurSel)); 629 if (p != NULL) { 630 param.m_pData = p; 631 } 632 } 633 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { 634 param.m_dwStates = FWL_PARTSTATE_CMB_Disabled; 635 } else if ((m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) && 636 (m_iCurSel >= 0)) { 637 param.m_dwStates = FWL_PARTSTATE_CMB_Selected; 638 } else { 639 param.m_dwStates = FWL_PARTSTATE_CMB_Normal; 640 } 641 pTheme->DrawBackground(¶m); 642 if (m_iCurSel >= 0) { 643 if (!m_pListBox) 644 return FWL_ERR_Indefinite; 645 CFX_WideString wsText; 646 IFWL_ComboBoxDP* pData = 647 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 648 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); 649 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 650 ->GetItemText(hItem, wsText); 651 CFWL_ThemeText param; 652 param.m_pWidget = m_pInterface; 653 param.m_iPart = FWL_PART_CMB_Caption; 654 param.m_dwStates = m_iBtnState; 655 param.m_pGraphics = pGraphics; 656 param.m_matrix.Concat(*pMatrix); 657 param.m_rtPart = rtTextBk; 658 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) 659 ? FWL_PARTSTATE_CMB_Selected 660 : FWL_PARTSTATE_CMB_Normal; 661 param.m_wsText = wsText; 662 param.m_dwTTOStyles = FDE_TTOSTYLE_SingleLine; 663 param.m_iTTOAlign = FDE_TTOALIGNMENT_CenterLeft; 664 pTheme->DrawText(¶m); 665 } 666 } 667 { 668 CFWL_ThemeBackground param; 669 param.m_pWidget = m_pInterface; 670 param.m_iPart = FWL_PART_CMB_DropDownButton; 671 param.m_dwStates = (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) 672 ? FWL_PARTSTATE_CMB_Disabled 673 : m_iBtnState; 674 param.m_pGraphics = pGraphics; 675 param.m_matrix.Concat(*pMatrix); 676 param.m_rtPart = m_rtBtn; 677 pTheme->DrawBackground(¶m); 678 } 679 return FWL_ERR_Succeeded; 680 } 681 FWL_ERR CFWL_ComboBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { 682 if (!pThemeProvider) 683 return FWL_ERR_Indefinite; 684 m_pProperties->m_pThemeProvider = pThemeProvider; 685 if (m_pListBox && pThemeProvider->IsValidWidget(m_pListBox.get())) { 686 m_pListBox->SetThemeProvider(pThemeProvider); 687 } 688 if (m_pEdit && pThemeProvider->IsValidWidget(m_pEdit.get())) { 689 m_pEdit->SetThemeProvider(pThemeProvider); 690 } 691 return FWL_ERR_Succeeded; 692 } 693 int32_t CFWL_ComboBoxImp::GetCurSel() { 694 return m_iCurSel; 695 } 696 FWL_ERR CFWL_ComboBoxImp::SetCurSel(int32_t iSel) { 697 int32_t iCount = 698 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->CountItems(); 699 FX_BOOL bClearSel = iSel < 0 || iSel >= iCount; 700 FX_BOOL bDropDown = IsDropDownStyle(); 701 if (bDropDown && m_pEdit) { 702 if (bClearSel) { 703 m_pEdit->SetText(CFX_WideString()); 704 } else { 705 CFX_WideString wsText; 706 IFWL_ComboBoxDP* pData = 707 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 708 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iSel); 709 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 710 ->GetItemText(hItem, wsText); 711 m_pEdit->SetText(wsText); 712 } 713 m_pEdit->Update(); 714 } 715 m_iCurSel = bClearSel ? -1 : iSel; 716 return FWL_ERR_Succeeded; 717 } 718 FWL_ERR CFWL_ComboBoxImp::SetStates(FX_DWORD dwStates, FX_BOOL bSet) { 719 FX_BOOL bIsDropDown = IsDropDownStyle(); 720 if (bIsDropDown && m_pEdit) { 721 m_pEdit->SetStates(dwStates, bSet); 722 } 723 if (m_pListBox) { 724 m_pListBox->SetStates(dwStates, bSet); 725 } 726 return CFWL_WidgetImp::SetStates(dwStates, bSet); 727 } 728 FWL_ERR CFWL_ComboBoxImp::SetEditText(const CFX_WideString& wsText) { 729 if (!m_pEdit) 730 return FWL_ERR_Indefinite; 731 m_pEdit->SetText(wsText); 732 return m_pEdit->Update(); 733 } 734 int32_t CFWL_ComboBoxImp::GetEditTextLength() const { 735 if (!m_pEdit) 736 return -1; 737 return m_pEdit->GetTextLength(); 738 } 739 FWL_ERR CFWL_ComboBoxImp::GetEditText(CFX_WideString& wsText, 740 int32_t nStart, 741 int32_t nCount) const { 742 if (m_pEdit) { 743 return m_pEdit->GetText(wsText, nStart, nCount); 744 } else if (m_pListBox) { 745 IFWL_ComboBoxDP* pData = 746 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 747 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); 748 return m_pListBox->GetItemText(hItem, wsText); 749 } 750 return FWL_ERR_Indefinite; 751 } 752 FWL_ERR CFWL_ComboBoxImp::SetEditSelRange(int32_t nStart, int32_t nCount) { 753 if (!m_pEdit) 754 return FWL_ERR_Indefinite; 755 static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->ClearSelected(); 756 m_pEdit->AddSelRange(nStart, nCount); 757 return FWL_ERR_Succeeded; 758 } 759 int32_t CFWL_ComboBoxImp::GetEditSelRange(int32_t nIndex, int32_t& nStart) { 760 if (!m_pEdit) 761 return -1; 762 return m_pEdit->GetSelRange(nIndex, nStart); 763 } 764 int32_t CFWL_ComboBoxImp::GetEditLimit() { 765 if (!m_pEdit) 766 return -1; 767 return m_pEdit->GetLimit(); 768 } 769 FWL_ERR CFWL_ComboBoxImp::SetEditLimit(int32_t nLimit) { 770 if (!m_pEdit) 771 return FWL_ERR_Indefinite; 772 return m_pEdit->SetLimit(nLimit); 773 } 774 FWL_ERR CFWL_ComboBoxImp::EditDoClipboard(int32_t iCmd) { 775 if (!m_pEdit) 776 return FWL_ERR_Indefinite; 777 return m_pEdit->DoClipboard(iCmd); 778 } 779 FX_BOOL CFWL_ComboBoxImp::EditRedo(const CFX_ByteStringC& bsRecord) { 780 if (!m_pEdit) 781 return FALSE; 782 return m_pEdit->Redo(bsRecord); 783 } 784 FX_BOOL CFWL_ComboBoxImp::EditUndo(const CFX_ByteStringC& bsRecord) { 785 if (!m_pEdit) 786 return FALSE; 787 return m_pEdit->Undo(bsRecord); 788 } 789 IFWL_ListBox* CFWL_ComboBoxImp::GetListBoxt() { 790 return m_pListBox.get(); 791 } 792 FX_BOOL CFWL_ComboBoxImp::AfterFocusShowDropList() { 793 if (!m_bNeedShowList) { 794 return FALSE; 795 } 796 if (m_pEdit) { 797 MatchEditText(); 798 } 799 ShowDropList(TRUE); 800 m_bNeedShowList = FALSE; 801 return TRUE; 802 } 803 FX_ERR CFWL_ComboBoxImp::OpenDropDownList(FX_BOOL bActivate) { 804 ShowDropList(bActivate); 805 return FWL_ERR_Succeeded; 806 } 807 FX_BOOL CFWL_ComboBoxImp::EditCanUndo() { 808 return m_pEdit->CanUndo(); 809 } 810 FX_BOOL CFWL_ComboBoxImp::EditCanRedo() { 811 return m_pEdit->CanRedo(); 812 } 813 FX_BOOL CFWL_ComboBoxImp::EditUndo() { 814 return m_pEdit->Undo(); 815 } 816 FX_BOOL CFWL_ComboBoxImp::EditRedo() { 817 return m_pEdit->Redo(); 818 } 819 FX_BOOL CFWL_ComboBoxImp::EditCanCopy() { 820 return m_pEdit->CountSelRanges() > 0; 821 } 822 FX_BOOL CFWL_ComboBoxImp::EditCanCut() { 823 if (m_pEdit->GetStylesEx() & FWL_STYLEEXT_EDT_ReadOnly) { 824 return FALSE; 825 } 826 return m_pEdit->CountSelRanges() > 0; 827 } 828 FX_BOOL CFWL_ComboBoxImp::EditCanSelectAll() { 829 return m_pEdit->GetTextLength() > 0; 830 } 831 FX_BOOL CFWL_ComboBoxImp::EditCopy(CFX_WideString& wsCopy) { 832 return m_pEdit->Copy(wsCopy); 833 } 834 FX_BOOL CFWL_ComboBoxImp::EditCut(CFX_WideString& wsCut) { 835 return m_pEdit->Cut(wsCut); 836 } 837 FX_BOOL CFWL_ComboBoxImp::EditPaste(const CFX_WideString& wsPaste) { 838 return m_pEdit->Paste(wsPaste); 839 } 840 FX_BOOL CFWL_ComboBoxImp::EditSelectAll() { 841 return m_pEdit->AddSelRange(0) == FWL_ERR_Succeeded; 842 } 843 FX_BOOL CFWL_ComboBoxImp::EditDelete() { 844 return m_pEdit->ClearText() == FWL_ERR_Succeeded; 845 } 846 FX_BOOL CFWL_ComboBoxImp::EditDeSelect() { 847 return m_pEdit->ClearSelections() == FWL_ERR_Succeeded; 848 } 849 FWL_ERR CFWL_ComboBoxImp::GetBBox(CFX_RectF& rect) { 850 if (m_pWidgetMgr->IsFormDisabled()) { 851 return DisForm_GetBBox(rect); 852 } 853 rect = m_pProperties->m_rtWidget; 854 if (m_pListBox && IsDropListShowed()) { 855 CFX_RectF rtList; 856 m_pListBox->GetWidgetRect(rtList); 857 rtList.Offset(rect.left, rect.top); 858 rect.Union(rtList); 859 } 860 return FWL_ERR_Succeeded; 861 } 862 FWL_ERR CFWL_ComboBoxImp::EditModifyStylesEx(FX_DWORD dwStylesExAdded, 863 FX_DWORD dwStylesExRemoved) { 864 if (m_pEdit != NULL) { 865 return m_pEdit->ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); 866 } else { 867 return FWL_ERR_Parameter_Invalid; 868 } 869 } 870 FX_FLOAT CFWL_ComboBoxImp::GetListHeight() { 871 return static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider) 872 ->GetListHeight(m_pInterface); 873 } 874 void CFWL_ComboBoxImp::DrawStretchHandler(CFX_Graphics* pGraphics, 875 const CFX_Matrix* pMatrix) { 876 CFWL_ThemeBackground param; 877 param.m_pGraphics = pGraphics; 878 param.m_iPart = FWL_PART_CMB_StretcgHandler; 879 param.m_dwStates = FWL_PARTSTATE_CMB_Normal; 880 param.m_pWidget = m_pInterface; 881 if (pMatrix) { 882 param.m_matrix.Concat(*pMatrix); 883 } 884 param.m_rtPart = m_rtHandler; 885 m_pProperties->m_pThemeProvider->DrawBackground(¶m); 886 } 887 void CFWL_ComboBoxImp::ShowDropList(FX_BOOL bActivate) { 888 if (m_pWidgetMgr->IsFormDisabled()) { 889 return DisForm_ShowDropList(bActivate); 890 } 891 FX_BOOL bDropList = IsDropListShowed(); 892 if (bDropList == bActivate) { 893 return; 894 } 895 if (!m_pForm) { 896 InitProxyForm(); 897 } 898 m_pListProxyDelegate->Reset(); 899 if (bActivate) { 900 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 901 ->ChangeSelected(m_iCurSel); 902 ReSetListItemAlignment(); 903 FX_DWORD dwStyleAdd = m_pProperties->m_dwStyleExes & 904 (FWL_STYLEEXT_CMB_Sort | FWL_STYLEEXT_CMB_OwnerDraw); 905 m_pListBox->ModifyStylesEx(dwStyleAdd, 0); 906 m_pListBox->GetWidgetRect(m_rtList, TRUE); 907 FX_FLOAT fHeight = GetListHeight(); 908 if (fHeight > 0) { 909 if (m_rtList.height > GetListHeight()) { 910 m_rtList.height = GetListHeight(); 911 m_pListBox->ModifyStyles(FWL_WGTSTYLE_VScroll, 0); 912 } 913 } 914 CFX_RectF rtAnchor; 915 rtAnchor.Set(0, 0, m_pProperties->m_rtWidget.width, 916 m_pProperties->m_rtWidget.height); 917 FX_FLOAT fMinHeight = 0; 918 if (m_rtList.width < m_rtClient.width) { 919 m_rtList.width = m_rtClient.width; 920 } 921 m_rtProxy = m_rtList; 922 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) { 923 m_rtProxy.height += m_fComboFormHandler; 924 } 925 GetPopupPos(fMinHeight, m_rtProxy.height, rtAnchor, m_rtProxy); 926 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_ListDrag) { 927 FX_FLOAT fx = 0; 928 FX_FLOAT fy = m_rtClient.top + m_rtClient.height / 2; 929 TransformTo(NULL, fx, fy); 930 m_bUpFormHandler = fy > m_rtProxy.top; 931 if (m_bUpFormHandler) { 932 m_rtHandler.Set(0, 0, m_rtList.width, m_fComboFormHandler); 933 m_rtList.top = m_fComboFormHandler; 934 } else { 935 m_rtHandler.Set(0, m_rtList.height, m_rtList.width, 936 m_fComboFormHandler); 937 } 938 } 939 m_pForm->SetWidgetRect(m_rtProxy); 940 m_pForm->Update(); 941 m_pListBox->SetWidgetRect(m_rtList); 942 m_pListBox->Update(); 943 CFWL_EvtCmbPreDropDown ev; 944 ev.m_pSrcTarget = m_pInterface; 945 DispatchEvent(&ev); 946 m_fItemHeight = 947 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_fItemHeight; 948 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(TRUE); 949 m_pForm->DoModal(); 950 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->SetFocus(FALSE); 951 } else { 952 m_pForm->EndDoModal(); 953 CFWL_EvtCmbCloseUp ev; 954 ev.m_pSrcTarget = m_pInterface; 955 DispatchEvent(&ev); 956 m_bLButtonDown = FALSE; 957 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->m_bNotifyOwner = 958 TRUE; 959 SetFocus(TRUE); 960 } 961 } 962 FX_BOOL CFWL_ComboBoxImp::IsDropListShowed() { 963 return m_pForm && !(m_pForm->GetStates() & FWL_WGTSTATE_Invisible); 964 } 965 FX_BOOL CFWL_ComboBoxImp::IsDropDownStyle() const { 966 return m_pProperties->m_dwStyleExes & FWL_STYLEEXT_CMB_DropDown; 967 } 968 void CFWL_ComboBoxImp::MatchEditText() { 969 CFX_WideString wsText; 970 m_pEdit->GetText(wsText); 971 int32_t iMatch = 972 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl())->MatchItem(wsText); 973 if (iMatch != m_iCurSel) { 974 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 975 ->ChangeSelected(iMatch); 976 if (iMatch >= 0) { 977 SynchrEditText(iMatch); 978 } 979 } else if (iMatch >= 0) { 980 static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); 981 } 982 m_iCurSel = iMatch; 983 } 984 void CFWL_ComboBoxImp::SynchrEditText(int32_t iListItem) { 985 CFX_WideString wsText; 986 IFWL_ComboBoxDP* pData = 987 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 988 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iListItem); 989 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 990 ->GetItemText(hItem, wsText); 991 m_pEdit->SetText(wsText); 992 m_pEdit->Update(); 993 static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); 994 } 995 void CFWL_ComboBoxImp::Layout() { 996 if (m_pWidgetMgr->IsFormDisabled()) { 997 return DisForm_Layout(); 998 } 999 GetClientRect(m_rtClient); 1000 FX_FLOAT* pFWidth = 1001 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); 1002 if (!pFWidth) 1003 return; 1004 FX_FLOAT fBtn = *pFWidth; 1005 m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top, fBtn, 1006 m_rtClient.height); 1007 FX_BOOL bIsDropDown = IsDropDownStyle(); 1008 if (bIsDropDown && m_pEdit) { 1009 CFX_RectF rtEdit; 1010 rtEdit.Set(m_rtClient.left, m_rtClient.top, m_rtClient.width - fBtn, 1011 m_rtClient.height); 1012 m_pEdit->SetWidgetRect(rtEdit); 1013 if (m_iCurSel >= 0) { 1014 CFX_WideString wsText; 1015 IFWL_ComboBoxDP* pData = 1016 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 1017 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); 1018 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 1019 ->GetItemText(hItem, wsText); 1020 m_pEdit->LockUpdate(); 1021 m_pEdit->SetText(wsText); 1022 m_pEdit->UnlockUpdate(); 1023 } 1024 m_pEdit->Update(); 1025 } 1026 } 1027 void CFWL_ComboBoxImp::ReSetTheme() { 1028 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; 1029 if (!pTheme) { 1030 pTheme = GetAvailableTheme(); 1031 m_pProperties->m_pThemeProvider = pTheme; 1032 } 1033 if (m_pListBox) { 1034 if (!m_pListBox->GetThemeProvider() && 1035 pTheme->IsValidWidget(m_pListBox.get())) { 1036 m_pListBox->SetThemeProvider(pTheme); 1037 } 1038 } 1039 if (m_pEdit) { 1040 if (!m_pEdit->GetThemeProvider() && pTheme->IsValidWidget(m_pEdit.get())) { 1041 m_pEdit->SetThemeProvider(pTheme); 1042 } 1043 } 1044 } 1045 void CFWL_ComboBoxImp::ReSetEditAlignment() { 1046 if (!m_pEdit) 1047 return; 1048 FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes; 1049 FX_DWORD dwAdd = 0; 1050 switch (dwStylExes & FWL_STYLEEXT_CMB_EditHAlignMask) { 1051 case FWL_STYLEEXT_CMB_EditHCenter: { 1052 dwAdd |= FWL_STYLEEXT_EDT_HCenter; 1053 break; 1054 } 1055 case FWL_STYLEEXT_CMB_EditHFar: { 1056 dwAdd |= FWL_STYLEEXT_EDT_HFar; 1057 break; 1058 } 1059 default: { dwAdd |= FWL_STYLEEXT_EDT_HNear; } 1060 } 1061 switch (dwStylExes & FWL_STYLEEXT_CMB_EditVAlignMask) { 1062 case FWL_STYLEEXT_CMB_EditVCenter: { 1063 dwAdd |= FWL_STYLEEXT_EDT_VCenter; 1064 break; 1065 } 1066 case FWL_STYLEEXT_CMB_EditVFar: { 1067 dwAdd |= FWL_STYLEEXT_EDT_VFar; 1068 break; 1069 } 1070 default: { dwAdd |= FWL_STYLEEXT_EDT_VNear; } 1071 } 1072 if (dwStylExes & FWL_STYLEEXT_CMB_EditJustified) { 1073 dwAdd |= FWL_STYLEEXT_EDT_Justified; 1074 } 1075 if (dwStylExes & FWL_STYLEEXT_CMB_EditDistributed) { 1076 dwAdd |= FWL_STYLEEXT_EDT_Distributed; 1077 } 1078 m_pEdit->ModifyStylesEx(dwAdd, FWL_STYLEEXT_EDT_HAlignMask | 1079 FWL_STYLEEXT_EDT_HAlignModeMask | 1080 FWL_STYLEEXT_EDT_VAlignMask); 1081 } 1082 void CFWL_ComboBoxImp::ReSetListItemAlignment() { 1083 if (!m_pListBox) 1084 return; 1085 FX_DWORD dwStylExes = m_pProperties->m_dwStyleExes; 1086 FX_DWORD dwAdd = 0; 1087 switch (dwStylExes & FWL_STYLEEXT_CMB_ListItemAlignMask) { 1088 case FWL_STYLEEXT_CMB_ListItemCenterAlign: { 1089 dwAdd |= FWL_STYLEEXT_LTB_CenterAlign; 1090 } 1091 case FWL_STYLEEXT_CMB_ListItemRightAlign: { 1092 dwAdd |= FWL_STYLEEXT_LTB_RightAlign; 1093 } 1094 default: { dwAdd |= FWL_STYLEEXT_LTB_LeftAlign; } 1095 } 1096 m_pListBox->ModifyStylesEx(dwAdd, FWL_STYLEEXT_CMB_ListItemAlignMask); 1097 } 1098 void CFWL_ComboBoxImp::ProcessSelChanged(FX_BOOL bLButtonUp) { 1099 IFWL_ComboBoxDP* pDatas = 1100 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 1101 m_iCurSel = pDatas->GetItemIndex(m_pInterface, m_pListBox->GetSelItem(0)); 1102 FX_BOOL bDropDown = IsDropDownStyle(); 1103 if (bDropDown) { 1104 IFWL_ComboBoxDP* pData = 1105 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 1106 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); 1107 if (hItem) { 1108 CFX_WideString wsText; 1109 pData->GetItemText(m_pInterface, hItem, wsText); 1110 if (m_pEdit) { 1111 m_pEdit->SetText(wsText); 1112 m_pEdit->Update(); 1113 static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetSelected(); 1114 } 1115 CFWL_EvtCmbSelChanged ev; 1116 ev.bLButtonUp = bLButtonUp; 1117 ev.m_pSrcTarget = m_pInterface; 1118 ev.iArraySels.Add(m_iCurSel); 1119 DispatchEvent(&ev); 1120 } 1121 } else { 1122 Repaint(&m_rtClient); 1123 } 1124 } 1125 void CFWL_ComboBoxImp::InitProxyForm() { 1126 if (m_pForm) 1127 return; 1128 if (!m_pListBox) 1129 return; 1130 CFWL_WidgetImpProperties propForm; 1131 propForm.m_pOwner = m_pInterface; 1132 propForm.m_dwStyles = FWL_WGTSTYLE_Popup; 1133 propForm.m_dwStates = FWL_WGTSTATE_Invisible; 1134 CFX_WideString className; 1135 m_pForm = IFWL_Form::CreateFormProxy(propForm, &className, m_pListBox.get()); 1136 m_pForm->Initialize(); 1137 m_pProxy = static_cast<CFWL_FormProxyImp*>(m_pForm->GetImpl()); 1138 m_pListBox->SetParent(m_pForm); 1139 m_pListProxyDelegate = new CFWL_ComboProxyImpDelegate(m_pForm, this); 1140 m_pProxy->SetDelegate(m_pListProxyDelegate); 1141 } 1142 FWL_ERR CFWL_ComboBoxImp::DisForm_Initialize() { 1143 if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) 1144 return FWL_WGTSTATE_Invisible; // Ditto. 1145 m_pDelegate = new CFWL_ComboBoxImpDelegate(this); 1146 DisForm_InitComboList(); 1147 DisForm_InitComboEdit(); 1148 return FWL_ERR_Succeeded; 1149 } 1150 void CFWL_ComboBoxImp::DisForm_InitComboList() { 1151 if (m_pListBox) { 1152 return; 1153 } 1154 CFWL_WidgetImpProperties prop; 1155 prop.m_pParent = m_pInterface; 1156 prop.m_dwStyles = FWL_WGTSTYLE_Border | FWL_WGTSTYLE_VScroll; 1157 prop.m_dwStates = FWL_WGTSTATE_Invisible; 1158 prop.m_pDataProvider = m_pProperties->m_pDataProvider; 1159 prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; 1160 m_pListBox.reset(IFWL_ListBox::CreateComboList(prop, m_pInterface)); 1161 m_pListBox->Initialize(); 1162 } 1163 void CFWL_ComboBoxImp::DisForm_InitComboEdit() { 1164 if (m_pEdit) { 1165 return; 1166 } 1167 CFWL_WidgetImpProperties prop; 1168 prop.m_pParent = m_pInterface; 1169 prop.m_pThemeProvider = m_pProperties->m_pThemeProvider; 1170 m_pEdit.reset(IFWL_Edit::CreateComboEdit(prop, m_pInterface)); 1171 m_pEdit->Initialize(); 1172 static_cast<CFWL_ComboEditImp*>(m_pEdit->GetImpl())->SetOuter(m_pInterface); 1173 } 1174 void CFWL_ComboBoxImp::DisForm_ShowDropList(FX_BOOL bActivate) { 1175 FX_BOOL bDropList = DisForm_IsDropListShowed(); 1176 if (bDropList == bActivate) { 1177 return; 1178 } 1179 if (bActivate) { 1180 CFWL_EvtCmbPreDropDown preEvent; 1181 preEvent.m_pSrcTarget = m_pInterface; 1182 DispatchEvent(&preEvent); 1183 CFWL_ComboListImp* pComboList = 1184 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()); 1185 int32_t iItems = pComboList->CountItems(); 1186 if (iItems < 1) { 1187 return; 1188 } 1189 ReSetListItemAlignment(); 1190 pComboList->ChangeSelected(m_iCurSel); 1191 FX_FLOAT fItemHeight = pComboList->GetItemHeigt(); 1192 FX_FLOAT fBorder = GetBorderSize(); 1193 FX_FLOAT fPopupMin = 0.0f; 1194 if (iItems > 3) { 1195 fPopupMin = fItemHeight * 3 + fBorder * 2; 1196 } 1197 FX_FLOAT fPopupMax = fItemHeight * iItems + fBorder * 2; 1198 CFX_RectF rtList; 1199 rtList.left = m_rtClient.left; 1200 rtList.width = m_pProperties->m_rtWidget.width; 1201 rtList.top = 0; 1202 rtList.height = 0; 1203 GetPopupPos(fPopupMin, fPopupMax, m_pProperties->m_rtWidget, rtList); 1204 m_pListBox->SetWidgetRect(rtList); 1205 m_pListBox->Update(); 1206 } else { 1207 SetFocus(TRUE); 1208 } 1209 m_pListBox->SetStates(FWL_WGTSTATE_Invisible, !bActivate); 1210 if (bActivate) { 1211 CFWL_EvtCmbPostDropDown postEvent; 1212 postEvent.m_pSrcTarget = m_pInterface; 1213 DispatchEvent(&postEvent); 1214 } 1215 CFX_RectF rect; 1216 m_pListBox->GetWidgetRect(rect); 1217 rect.Inflate(2, 2); 1218 Repaint(&rect); 1219 } 1220 FX_BOOL CFWL_ComboBoxImp::DisForm_IsDropListShowed() { 1221 return !(m_pListBox->GetStates() & FWL_WGTSTATE_Invisible); 1222 } 1223 FWL_ERR CFWL_ComboBoxImp::DisForm_ModifyStylesEx(FX_DWORD dwStylesExAdded, 1224 FX_DWORD dwStylesExRemoved) { 1225 if (!m_pEdit) { 1226 DisForm_InitComboEdit(); 1227 } 1228 FX_BOOL bAddDropDown = dwStylesExAdded & FWL_STYLEEXT_CMB_DropDown; 1229 FX_BOOL bDelDropDown = dwStylesExRemoved & FWL_STYLEEXT_CMB_DropDown; 1230 dwStylesExRemoved &= ~FWL_STYLEEXT_CMB_DropDown; 1231 m_pProperties->m_dwStyleExes |= FWL_STYLEEXT_CMB_DropDown; 1232 if (bAddDropDown) { 1233 m_pEdit->ModifyStylesEx(0, FWL_STYLEEXT_EDT_ReadOnly); 1234 } else if (bDelDropDown) { 1235 m_pEdit->ModifyStylesEx(FWL_STYLEEXT_EDT_ReadOnly, 0); 1236 } 1237 return CFWL_WidgetImp::ModifyStylesEx(dwStylesExAdded, dwStylesExRemoved); 1238 } 1239 FWL_ERR CFWL_ComboBoxImp::DisForm_Update() { 1240 if (m_iLock) { 1241 return FWL_ERR_Indefinite; 1242 } 1243 if (m_pEdit) { 1244 ReSetEditAlignment(); 1245 } 1246 ReSetTheme(); 1247 Layout(); 1248 return FWL_ERR_Succeeded; 1249 } 1250 FX_DWORD CFWL_ComboBoxImp::DisForm_HitTest(FX_FLOAT fx, FX_FLOAT fy) { 1251 CFX_RectF rect; 1252 rect.Set(0, 0, m_pProperties->m_rtWidget.width - m_rtBtn.width, 1253 m_pProperties->m_rtWidget.height); 1254 if (rect.Contains(fx, fy)) { 1255 return FWL_WGTHITTEST_Edit; 1256 } 1257 if (m_rtBtn.Contains(fx, fy)) { 1258 return FWL_WGTHITTEST_Client; 1259 } 1260 if (DisForm_IsDropListShowed()) { 1261 m_pListBox->GetWidgetRect(rect); 1262 if (rect.Contains(fx, fy)) { 1263 return FWL_WGTHITTEST_Client; 1264 } 1265 } 1266 return FWL_WGTHITTEST_Unknown; 1267 } 1268 FWL_ERR CFWL_ComboBoxImp::DisForm_DrawWidget(CFX_Graphics* pGraphics, 1269 const CFX_Matrix* pMatrix) { 1270 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; 1271 CFX_Matrix mtOrg; 1272 mtOrg.Set(1, 0, 0, 1, 0, 0); 1273 if (pMatrix) { 1274 mtOrg = *pMatrix; 1275 } 1276 FX_BOOL bListShowed = m_pListBox && DisForm_IsDropListShowed(); 1277 pGraphics->SaveGraphState(); 1278 pGraphics->ConcatMatrix(&mtOrg); 1279 if (!m_rtBtn.IsEmpty(0.1f)) { 1280 CFWL_ThemeBackground param; 1281 param.m_pWidget = m_pInterface; 1282 param.m_iPart = FWL_PART_CMB_DropDownButton; 1283 param.m_dwStates = m_iBtnState; 1284 param.m_pGraphics = pGraphics; 1285 param.m_rtPart = m_rtBtn; 1286 pTheme->DrawBackground(¶m); 1287 } 1288 pGraphics->RestoreGraphState(); 1289 if (m_pEdit) { 1290 CFX_RectF rtEdit; 1291 m_pEdit->GetWidgetRect(rtEdit); 1292 CFX_Matrix mt; 1293 mt.Set(1, 0, 0, 1, rtEdit.left, rtEdit.top); 1294 mt.Concat(mtOrg); 1295 m_pEdit->DrawWidget(pGraphics, &mt); 1296 } 1297 if (bListShowed) { 1298 CFX_RectF rtList; 1299 m_pListBox->GetWidgetRect(rtList); 1300 CFX_Matrix mt; 1301 mt.Set(1, 0, 0, 1, rtList.left, rtList.top); 1302 mt.Concat(mtOrg); 1303 m_pListBox->DrawWidget(pGraphics, &mt); 1304 } 1305 return FWL_ERR_Succeeded; 1306 } 1307 FWL_ERR CFWL_ComboBoxImp::DisForm_GetBBox(CFX_RectF& rect) { 1308 rect = m_pProperties->m_rtWidget; 1309 if (m_pListBox && DisForm_IsDropListShowed()) { 1310 CFX_RectF rtList; 1311 m_pListBox->GetWidgetRect(rtList); 1312 rtList.Offset(rect.left, rect.top); 1313 rect.Union(rtList); 1314 } 1315 return FWL_ERR_Succeeded; 1316 } 1317 void CFWL_ComboBoxImp::DisForm_Layout() { 1318 GetClientRect(m_rtClient); 1319 m_rtContent = m_rtClient; 1320 FX_FLOAT* pFWidth = 1321 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); 1322 if (!pFWidth) 1323 return; 1324 FX_FLOAT borderWidth = 0; 1325 { borderWidth = FWL_PART_CMB_Border; } 1326 FX_FLOAT fBtn = *pFWidth; 1327 if (!(this->GetStylesEx() & FWL_STYLEEXT_CMB_ReadOnly)) { 1328 m_rtBtn.Set(m_rtClient.right() - fBtn, m_rtClient.top + borderWidth, 1329 fBtn - borderWidth, m_rtClient.height - 2 * borderWidth); 1330 } 1331 CFX_RectF* pUIMargin = 1332 static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin)); 1333 if (pUIMargin) { 1334 m_rtContent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, 1335 pUIMargin->height); 1336 } 1337 FX_BOOL bIsDropDown = IsDropDownStyle(); 1338 if (bIsDropDown && m_pEdit) { 1339 CFX_RectF rtEdit; 1340 rtEdit.Set(m_rtContent.left, m_rtContent.top, m_rtContent.width - fBtn, 1341 m_rtContent.height); 1342 m_pEdit->SetWidgetRect(rtEdit); 1343 if (m_iCurSel >= 0) { 1344 CFX_WideString wsText; 1345 IFWL_ComboBoxDP* pData = 1346 static_cast<IFWL_ComboBoxDP*>(m_pProperties->m_pDataProvider); 1347 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, m_iCurSel); 1348 static_cast<CFWL_ComboListImp*>(m_pListBox->GetImpl()) 1349 ->GetItemText(hItem, wsText); 1350 m_pEdit->LockUpdate(); 1351 m_pEdit->SetText(wsText); 1352 m_pEdit->UnlockUpdate(); 1353 } 1354 m_pEdit->Update(); 1355 } 1356 } 1357 CFWL_ComboBoxImpDelegate::CFWL_ComboBoxImpDelegate(CFWL_ComboBoxImp* pOwner) 1358 : m_pOwner(pOwner) {} 1359 int32_t CFWL_ComboBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { 1360 if (m_pOwner->m_pWidgetMgr->IsFormDisabled()) { 1361 return DisForm_OnProcessMessage(pMessage); 1362 } 1363 if (!pMessage) 1364 return 0; 1365 FX_DWORD dwMsgCode = pMessage->GetClassID(); 1366 FX_BOOL iRet = 1; 1367 switch (dwMsgCode) { 1368 case FWL_MSGHASH_SetFocus: 1369 case FWL_MSGHASH_KillFocus: { 1370 OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); 1371 break; 1372 } 1373 case FWL_MSGHASH_Mouse: { 1374 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 1375 FX_DWORD dwCmd = pMsg->m_dwCmd; 1376 switch (dwCmd) { 1377 case FWL_MSGMOUSECMD_LButtonDown: { 1378 OnLButtonDown(pMsg); 1379 break; 1380 } 1381 case FWL_MSGMOUSECMD_LButtonUp: { 1382 OnLButtonUp(pMsg); 1383 break; 1384 } 1385 case FWL_MSGMOUSECMD_MouseMove: { 1386 OnMouseMove(pMsg); 1387 break; 1388 } 1389 case FWL_MSGMOUSECMD_MouseLeave: { 1390 OnMouseLeave(pMsg); 1391 break; 1392 } 1393 default: {} 1394 } 1395 break; 1396 } 1397 case FWL_MSGHASH_Key: { 1398 OnKey(static_cast<CFWL_MsgKey*>(pMessage)); 1399 break; 1400 } 1401 default: { iRet = 0; } 1402 } 1403 CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); 1404 return iRet; 1405 } 1406 FWL_ERR CFWL_ComboBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { 1407 FX_DWORD dwFlag = pEvent->GetClassID(); 1408 if (dwFlag == FWL_EVTHASH_LTB_DrawItem) { 1409 CFWL_EvtLtbDrawItem* pDrawItemEvent = 1410 static_cast<CFWL_EvtLtbDrawItem*>(pEvent); 1411 CFWL_EvtCmbDrawItem pTemp; 1412 pTemp.m_pSrcTarget = m_pOwner->m_pInterface; 1413 pTemp.m_pGraphics = pDrawItemEvent->m_pGraphics; 1414 pTemp.m_index = pDrawItemEvent->m_index; 1415 pTemp.m_rtItem = pDrawItemEvent->m_rect; 1416 m_pOwner->DispatchEvent(&pTemp); 1417 } else if (dwFlag == FWL_EVTHASH_Scroll) { 1418 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); 1419 CFWL_EvtScroll pScrollEv; 1420 pScrollEv.m_pSrcTarget = m_pOwner->m_pInterface; 1421 pScrollEv.m_iScrollCode = pScrollEvent->m_iScrollCode; 1422 pScrollEv.m_fPos = pScrollEvent->m_fPos; 1423 m_pOwner->DispatchEvent(&pScrollEv); 1424 } else if (dwFlag == FWL_EVTHASH_EDT_TextChanged) { 1425 CFWL_EvtEdtTextChanged* pTextChangedEvent = 1426 static_cast<CFWL_EvtEdtTextChanged*>(pEvent); 1427 CFWL_EvtCmbEditChanged pTemp; 1428 pTemp.m_pSrcTarget = m_pOwner->m_pInterface; 1429 pTemp.wsInsert = pTextChangedEvent->wsInsert; 1430 pTemp.wsDelete = pTextChangedEvent->wsDelete; 1431 pTemp.nChangeType = pTextChangedEvent->nChangeType; 1432 m_pOwner->DispatchEvent(&pTemp); 1433 } 1434 return FWL_ERR_Succeeded; 1435 } 1436 FWL_ERR CFWL_ComboBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, 1437 const CFX_Matrix* pMatrix) { 1438 return m_pOwner->DrawWidget(pGraphics, pMatrix); 1439 } 1440 void CFWL_ComboBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg, 1441 FX_BOOL bSet) { 1442 IFWL_Target* pDstTarget = pMsg->m_pDstTarget; 1443 IFWL_Target* pSrcTarget = pMsg->m_pSrcTarget; 1444 FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); 1445 if (bSet) { 1446 m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; 1447 if (bDropDown && pSrcTarget != m_pOwner->m_pListBox.get()) { 1448 if (!m_pOwner->m_pEdit) 1449 return; 1450 static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) 1451 ->SetSelected(); 1452 } else { 1453 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1454 } 1455 } else { 1456 m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; 1457 if (bDropDown && pDstTarget != m_pOwner->m_pListBox.get()) { 1458 if (!m_pOwner->m_pEdit) 1459 return; 1460 static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) 1461 ->FlagFocus(FALSE); 1462 static_cast<CFWL_ComboEditImp*>(m_pOwner->m_pEdit->GetImpl()) 1463 ->ClearSelected(); 1464 } else { 1465 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1466 } 1467 } 1468 } 1469 void CFWL_ComboBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { 1470 if (m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { 1471 return; 1472 } 1473 FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); 1474 CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient; 1475 FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy); 1476 if (bClickBtn) { 1477 if (bDropDown && m_pOwner->m_pEdit) { 1478 m_pOwner->MatchEditText(); 1479 } 1480 m_pOwner->m_bLButtonDown = TRUE; 1481 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Pressed; 1482 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1483 m_pOwner->ShowDropList(TRUE); 1484 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; 1485 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1486 } 1487 } 1488 void CFWL_ComboBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { 1489 m_pOwner->m_bLButtonDown = FALSE; 1490 if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { 1491 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Hovered; 1492 } else { 1493 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; 1494 } 1495 m_pOwner->Repaint(&m_pOwner->m_rtBtn); 1496 } 1497 void CFWL_ComboBoxImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { 1498 int32_t iOldState = m_pOwner->m_iBtnState; 1499 if (m_pOwner->m_rtBtn.Contains(pMsg->m_fx, pMsg->m_fy)) { 1500 m_pOwner->m_iBtnState = m_pOwner->m_bLButtonDown 1501 ? FWL_PARTSTATE_CMB_Pressed 1502 : FWL_PARTSTATE_CMB_Hovered; 1503 } else { 1504 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; 1505 } 1506 if ((iOldState != m_pOwner->m_iBtnState) && 1507 !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 1508 FWL_WGTSTATE_Disabled)) { 1509 m_pOwner->Repaint(&m_pOwner->m_rtBtn); 1510 } 1511 } 1512 void CFWL_ComboBoxImpDelegate::OnMouseLeave(CFWL_MsgMouse* pMsg) { 1513 if (!m_pOwner->IsDropListShowed() && 1514 !((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) == 1515 FWL_WGTSTATE_Disabled)) { 1516 m_pOwner->m_iBtnState = FWL_PARTSTATE_CMB_Normal; 1517 m_pOwner->Repaint(&m_pOwner->m_rtBtn); 1518 } 1519 } 1520 void CFWL_ComboBoxImpDelegate::OnKey(CFWL_MsgKey* pMsg) { 1521 FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; 1522 if (dwKeyCode == FWL_VKEY_Tab) { 1523 m_pOwner->DispatchKeyEvent(pMsg); 1524 return; 1525 } 1526 FX_BOOL bSubCtrlKey = pMsg->m_pDstTarget == m_pOwner->m_pInterface; 1527 if (bSubCtrlKey) { 1528 DoSubCtrlKey(pMsg); 1529 } 1530 } 1531 void CFWL_ComboBoxImpDelegate::DoSubCtrlKey(CFWL_MsgKey* pMsg) { 1532 FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; 1533 FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up; 1534 FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down; 1535 if (bUp || bDown) { 1536 int32_t iCount = static_cast<CFWL_ComboListImp*>( 1537 m_pOwner->m_pListBox->GetImpl())->CountItems(); 1538 if (iCount < 1) { 1539 return; 1540 } 1541 FX_BOOL bMatchEqual = FALSE; 1542 int32_t iCurSel = m_pOwner->m_iCurSel; 1543 FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); 1544 if (bDropDown && m_pOwner->m_pEdit) { 1545 CFX_WideString wsText; 1546 m_pOwner->m_pEdit->GetText(wsText); 1547 iCurSel = static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()) 1548 ->MatchItem(wsText); 1549 if (iCurSel >= 0) { 1550 CFX_WideString wsTemp; 1551 IFWL_ComboBoxDP* pData = static_cast<IFWL_ComboBoxDP*>( 1552 m_pOwner->m_pProperties->m_pDataProvider); 1553 FWL_HLISTITEM hItem = pData->GetItem(m_pOwner->m_pInterface, iCurSel); 1554 static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()) 1555 ->GetItemText(hItem, wsTemp); 1556 bMatchEqual = wsText.Equal(wsTemp); 1557 } 1558 } 1559 if (iCurSel < 0) { 1560 iCurSel = 0; 1561 } else if (!bDropDown || bMatchEqual) { 1562 if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) { 1563 return; 1564 } 1565 if (bUp) { 1566 iCurSel--; 1567 } else { 1568 iCurSel++; 1569 } 1570 } 1571 m_pOwner->m_iCurSel = iCurSel; 1572 if (bDropDown && m_pOwner->m_pEdit) { 1573 m_pOwner->SynchrEditText(m_pOwner->m_iCurSel); 1574 } else { 1575 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1576 } 1577 return; 1578 } 1579 FX_BOOL bDropDown = m_pOwner->IsDropDownStyle(); 1580 if (bDropDown) { 1581 IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); 1582 pDelegate->OnProcessMessage(pMsg); 1583 } 1584 } 1585 int32_t CFWL_ComboBoxImpDelegate::DisForm_OnProcessMessage( 1586 CFWL_Message* pMessage) { 1587 if (!pMessage) 1588 return 0; 1589 FX_DWORD dwMsgCode = pMessage->GetClassID(); 1590 FX_BOOL backDefault = TRUE; 1591 switch (dwMsgCode) { 1592 case FWL_MSGHASH_SetFocus: 1593 case FWL_MSGHASH_KillFocus: { 1594 backDefault = FALSE; 1595 DisForm_OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); 1596 break; 1597 } 1598 case FWL_MSGHASH_Mouse: { 1599 backDefault = FALSE; 1600 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 1601 FX_DWORD dwCmd = pMsg->m_dwCmd; 1602 switch (dwCmd) { 1603 case FWL_MSGMOUSECMD_LButtonDown: { 1604 DisForm_OnLButtonDown(pMsg); 1605 break; 1606 } 1607 case FWL_MSGMOUSECMD_LButtonUp: { 1608 OnLButtonUp(pMsg); 1609 break; 1610 } 1611 default: {} 1612 } 1613 break; 1614 } 1615 case FWL_MSGHASH_Key: { 1616 backDefault = FALSE; 1617 CFWL_MsgKey* pKey = static_cast<CFWL_MsgKey*>(pMessage); 1618 if (pKey->m_dwCmd == FWL_MSGKEYCMD_KeyUp) { 1619 break; 1620 } 1621 if (m_pOwner->DisForm_IsDropListShowed() && 1622 pKey->m_dwCmd == FWL_MSGKEYCMD_KeyDown) { 1623 FX_DWORD dwKeyCode = pKey->m_dwKeyCode; 1624 FX_BOOL bListKey = 1625 dwKeyCode == FWL_VKEY_Up || dwKeyCode == FWL_VKEY_Down || 1626 dwKeyCode == FWL_VKEY_Return || dwKeyCode == FWL_VKEY_Escape; 1627 if (bListKey) { 1628 IFWL_WidgetDelegate* pDelegate = 1629 m_pOwner->m_pListBox->SetDelegate(NULL); 1630 pDelegate->OnProcessMessage(pMessage); 1631 break; 1632 } 1633 } 1634 DisForm_OnKey(pKey); 1635 break; 1636 } 1637 default: {} 1638 } 1639 if (!backDefault) { 1640 return 1; 1641 } 1642 return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); 1643 } 1644 void CFWL_ComboBoxImpDelegate::DisForm_OnLButtonDown(CFWL_MsgMouse* pMsg) { 1645 FX_BOOL bDropDown = m_pOwner->DisForm_IsDropListShowed(); 1646 CFX_RectF& rtBtn = bDropDown ? m_pOwner->m_rtBtn : m_pOwner->m_rtClient; 1647 FX_BOOL bClickBtn = rtBtn.Contains(pMsg->m_fx, pMsg->m_fy); 1648 if (bClickBtn) { 1649 if (m_pOwner->DisForm_IsDropListShowed()) { 1650 m_pOwner->DisForm_ShowDropList(FALSE); 1651 return; 1652 } 1653 { 1654 if (m_pOwner->m_pEdit) { 1655 m_pOwner->MatchEditText(); 1656 } 1657 m_pOwner->DisForm_ShowDropList(TRUE); 1658 } 1659 } 1660 } 1661 void CFWL_ComboBoxImpDelegate::DisForm_OnFocusChanged(CFWL_Message* pMsg, 1662 FX_BOOL bSet) { 1663 if (bSet) { 1664 m_pOwner->m_pProperties->m_dwStates |= FWL_WGTSTATE_Focused; 1665 if ((m_pOwner->m_pEdit->GetStates() & FWL_WGTSTATE_Focused) == 0) { 1666 CFWL_MsgSetFocus msg; 1667 msg.m_pDstTarget = m_pOwner->m_pEdit.get(); 1668 msg.m_pSrcTarget = NULL; 1669 IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); 1670 pDelegate->OnProcessMessage(&msg); 1671 } 1672 } else { 1673 m_pOwner->m_pProperties->m_dwStates &= ~FWL_WGTSTATE_Focused; 1674 m_pOwner->DisForm_ShowDropList(FALSE); 1675 CFWL_MsgKillFocus msg; 1676 msg.m_pDstTarget = NULL; 1677 msg.m_pSrcTarget = m_pOwner->m_pEdit.get(); 1678 IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); 1679 pDelegate->OnProcessMessage(&msg); 1680 } 1681 } 1682 void CFWL_ComboBoxImpDelegate::DisForm_OnKey(CFWL_MsgKey* pMsg) { 1683 FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; 1684 FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up; 1685 FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down; 1686 if (bUp || bDown) { 1687 CFWL_ComboListImp* pComboList = 1688 static_cast<CFWL_ComboListImp*>(m_pOwner->m_pListBox->GetImpl()); 1689 int32_t iCount = pComboList->CountItems(); 1690 if (iCount < 1) { 1691 return; 1692 } 1693 FX_BOOL bMatchEqual = FALSE; 1694 int32_t iCurSel = m_pOwner->m_iCurSel; 1695 if (m_pOwner->m_pEdit) { 1696 CFX_WideString wsText; 1697 m_pOwner->m_pEdit->GetText(wsText); 1698 iCurSel = pComboList->MatchItem(wsText); 1699 if (iCurSel >= 0) { 1700 CFX_WideString wsTemp; 1701 FWL_HLISTITEM item = m_pOwner->m_pListBox->GetSelItem(iCurSel); 1702 m_pOwner->m_pListBox->GetItemText(item, wsTemp); 1703 bMatchEqual = wsText.Equal(wsTemp); 1704 } 1705 } 1706 if (iCurSel < 0) { 1707 iCurSel = 0; 1708 } else if (bMatchEqual) { 1709 if ((bUp && iCurSel == 0) || (bDown && iCurSel == iCount - 1)) { 1710 return; 1711 } 1712 if (bUp) { 1713 iCurSel--; 1714 } else { 1715 iCurSel++; 1716 } 1717 } 1718 m_pOwner->m_iCurSel = iCurSel; 1719 m_pOwner->SynchrEditText(m_pOwner->m_iCurSel); 1720 return; 1721 } 1722 if (m_pOwner->m_pEdit) { 1723 IFWL_WidgetDelegate* pDelegate = m_pOwner->m_pEdit->SetDelegate(NULL); 1724 pDelegate->OnProcessMessage(pMsg); 1725 } 1726 } 1727 CFWL_ComboProxyImpDelegate::CFWL_ComboProxyImpDelegate( 1728 IFWL_Form* pForm, 1729 CFWL_ComboBoxImp* pComboBox) 1730 : m_bLButtonDown(FALSE), 1731 m_bLButtonUpSelf(FALSE), 1732 m_fStartPos(0), 1733 m_pForm(pForm), 1734 m_pComboBox(pComboBox) { 1735 } 1736 int32_t CFWL_ComboProxyImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { 1737 if (!pMessage) 1738 return 0; 1739 FX_DWORD dwMsgCode = pMessage->GetClassID(); 1740 if (dwMsgCode == FWL_MSGHASH_Mouse) { 1741 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 1742 FX_DWORD dwCmd = pMsg->m_dwCmd; 1743 switch (dwCmd) { 1744 case FWL_MSGMOUSECMD_LButtonDown: { 1745 OnLButtonDown(pMsg); 1746 break; 1747 } 1748 case FWL_MSGMOUSECMD_LButtonUp: { 1749 OnLButtonUp(pMsg); 1750 break; 1751 } 1752 case FWL_MSGMOUSECMD_MouseMove: { 1753 OnMouseMove(pMsg); 1754 break; 1755 } 1756 default: {} 1757 } 1758 } 1759 if (dwMsgCode == FWL_MSGHASH_Deactivate) { 1760 OnDeactive(static_cast<CFWL_MsgDeactivate*>(pMessage)); 1761 } 1762 if (dwMsgCode == FWL_MSGHASH_KillFocus || dwMsgCode == FWL_MSGHASH_SetFocus) { 1763 OnFocusChanged(static_cast<CFWL_MsgKillFocus*>(pMessage), 1764 dwMsgCode == FWL_MSGHASH_SetFocus); 1765 } 1766 return CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); 1767 } 1768 FWL_ERR CFWL_ComboProxyImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, 1769 const CFX_Matrix* pMatrix) { 1770 m_pComboBox->DrawStretchHandler(pGraphics, pMatrix); 1771 return FWL_ERR_Succeeded; 1772 } 1773 void CFWL_ComboProxyImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { 1774 IFWL_NoteThread* pThread = m_pForm->GetOwnerThread(); 1775 if (!pThread) 1776 return; 1777 CFWL_NoteDriver* pDriver = 1778 static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver()); 1779 CFX_RectF rtWidget; 1780 m_pForm->GetWidgetRect(rtWidget); 1781 rtWidget.left = rtWidget.top = 0; 1782 if (rtWidget.Contains(pMsg->m_fx, pMsg->m_fy)) { 1783 m_bLButtonDown = TRUE; 1784 pDriver->SetGrab(m_pForm, TRUE); 1785 } else { 1786 m_bLButtonDown = FALSE; 1787 pDriver->SetGrab(m_pForm, FALSE); 1788 m_pComboBox->ShowDropList(FALSE); 1789 return; 1790 } 1791 IFWL_AdapterNative* pNative = FWL_GetAdapterNative(); 1792 IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr(); 1793 FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(FWL_CURSORTYPE_SizeNS); 1794 pCursorMgr->SetCursor(hCursor); 1795 pCursorMgr->ShowCursor(TRUE); 1796 m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy); 1797 m_fStartPos = pMsg->m_fy; 1798 } 1799 void CFWL_ComboProxyImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { 1800 m_bLButtonDown = FALSE; 1801 IFWL_NoteThread* pThread = m_pForm->GetOwnerThread(); 1802 if (!pThread) 1803 return; 1804 CFWL_NoteDriver* pDriver = 1805 static_cast<CFWL_NoteDriver*>(pThread->GetNoteDriver()); 1806 pDriver->SetGrab(m_pForm, FALSE); 1807 if (m_bLButtonUpSelf) { 1808 CFX_RectF rect; 1809 m_pForm->GetWidgetRect(rect); 1810 rect.left = rect.top = 0; 1811 if (!rect.Contains(pMsg->m_fx, pMsg->m_fy) && 1812 m_pComboBox->IsDropListShowed()) { 1813 m_pComboBox->ShowDropList(FALSE); 1814 } 1815 } else { 1816 m_bLButtonUpSelf = TRUE; 1817 } 1818 } 1819 void CFWL_ComboProxyImpDelegate::OnMouseMove(CFWL_MsgMouse* pMsg) { 1820 IFWL_AdapterNative* pNative = FWL_GetAdapterNative(); 1821 IFWL_AdapterCursorMgr* pCursorMgr = pNative->GetCursorMgr(); 1822 FWL_CURSORTYPE cursorType = FWL_CURSORTYPE_Arrow; 1823 if (m_pComboBox->m_rtHandler.Contains(pMsg->m_fx, pMsg->m_fy)) { 1824 cursorType = FWL_CURSORTYPE_SizeNS; 1825 } 1826 FWL_HCURSOR hCursor = pCursorMgr->GetSystemCursor(cursorType); 1827 pCursorMgr->SetCursor(hCursor); 1828 pCursorMgr->ShowCursor(TRUE); 1829 if (!m_bLButtonDown) { 1830 return; 1831 } 1832 m_pForm->TransformTo(NULL, pMsg->m_fx, pMsg->m_fy); 1833 FX_FLOAT fChanged = pMsg->m_fy - m_fStartPos; 1834 if (m_pComboBox->m_bUpFormHandler) { 1835 fChanged = m_fStartPos - pMsg->m_fy; 1836 } 1837 if (m_pComboBox->m_rtList.height + fChanged < m_pComboBox->m_fItemHeight) { 1838 return; 1839 } 1840 m_pComboBox->m_rtList.height += fChanged; 1841 m_pComboBox->m_rtProxy.height += fChanged; 1842 if (m_pComboBox->m_bUpFormHandler) { 1843 m_pComboBox->m_rtProxy.top -= fChanged; 1844 m_pComboBox->m_rtHandler.Set(0, 0, m_pComboBox->m_rtList.width, 1845 m_pComboBox->m_fComboFormHandler); 1846 } else { 1847 m_pComboBox->m_rtHandler.Set(0, m_pComboBox->m_rtList.height, 1848 m_pComboBox->m_rtList.width, 1849 m_pComboBox->m_fComboFormHandler); 1850 } 1851 m_pForm->SetWidgetRect(m_pComboBox->m_rtProxy); 1852 m_pComboBox->m_pListBox->SetWidgetRect(m_pComboBox->m_rtList); 1853 m_pComboBox->m_pListBox->Update(); 1854 m_fStartPos = pMsg->m_fy; 1855 } 1856 void CFWL_ComboProxyImpDelegate::OnDeactive(CFWL_MsgDeactivate* pMsg) { 1857 m_pComboBox->ShowDropList(FALSE); 1858 } 1859 void CFWL_ComboProxyImpDelegate::OnFocusChanged(CFWL_MsgKillFocus* pMsg, 1860 FX_BOOL bSet) { 1861 if (!bSet) { 1862 if (pMsg->m_pSetFocus == NULL) { 1863 m_pComboBox->ShowDropList(FALSE); 1864 } 1865 } 1866 } 1867