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_targetimp.h" 9 #include "xfa/src/fwl/src/core/include/fwl_noteimp.h" 10 #include "xfa/src/fwl/src/core/include/fwl_widgetimp.h" 11 #include "xfa/src/fwl/src/basewidget/include/fwl_scrollbarimp.h" 12 #include "xfa/src/fwl/src/basewidget/include/fwl_listboximp.h" 13 #include "xfa/src/fwl/src/basewidget/include/fwl_comboboximp.h" 14 15 #define FWL_LISTBOX_ItemTextMargin 2 16 17 // static 18 IFWL_ListBox* IFWL_ListBox::Create(const CFWL_WidgetImpProperties& properties, 19 IFWL_Widget* pOuter) { 20 IFWL_ListBox* pListBox = new IFWL_ListBox; 21 CFWL_ListBoxImp* pListBoxImpl = new CFWL_ListBoxImp(properties, pOuter); 22 pListBox->SetImpl(pListBoxImpl); 23 pListBoxImpl->SetInterface(pListBox); 24 return pListBox; 25 } 26 // static 27 IFWL_ListBox* IFWL_ListBox::CreateComboList( 28 const CFWL_WidgetImpProperties& properties, 29 IFWL_Widget* pOuter) { 30 IFWL_ListBox* pListBox = new IFWL_ListBox; 31 CFWL_ListBoxImp* pComboListImpl = new CFWL_ComboListImp(properties, pOuter); 32 pListBox->SetImpl(pComboListImpl); 33 pComboListImpl->SetInterface(pListBox); 34 return pListBox; 35 } 36 IFWL_ListBox::IFWL_ListBox() {} 37 int32_t IFWL_ListBox::CountSelItems() { 38 return static_cast<CFWL_ListBoxImp*>(GetImpl())->CountSelItems(); 39 } 40 FWL_HLISTITEM IFWL_ListBox::GetSelItem(int32_t nIndexSel) { 41 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelItem(nIndexSel); 42 } 43 int32_t IFWL_ListBox::GetSelIndex(int32_t nIndex) { 44 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetSelIndex(nIndex); 45 } 46 FWL_ERR IFWL_ListBox::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) { 47 return static_cast<CFWL_ListBoxImp*>(GetImpl())->SetSelItem(hItem, bSelect); 48 } 49 FWL_ERR IFWL_ListBox::GetItemText(FWL_HLISTITEM hItem, CFX_WideString& wsText) { 50 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetItemText(hItem, wsText); 51 } 52 FWL_ERR IFWL_ListBox::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) { 53 return static_cast<CFWL_ListBoxImp*>(GetImpl())->GetScrollPos(fPos, bVert); 54 } 55 FWL_ERR* IFWL_ListBox::Sort(IFWL_ListBoxCompare* pCom) { 56 return static_cast<CFWL_ListBoxImp*>(GetImpl())->Sort(pCom); 57 } 58 59 CFWL_ListBoxImp::CFWL_ListBoxImp(const CFWL_WidgetImpProperties& properties, 60 IFWL_Widget* pOuter) 61 : CFWL_WidgetImp(properties, pOuter), 62 m_dwTTOStyles(0), 63 m_iTTOAligns(0), 64 m_hAnchor(NULL), 65 m_fScorllBarWidth(0), 66 m_bLButtonDown(FALSE), 67 m_pScrollBarTP(NULL) { 68 m_rtClient.Reset(); 69 m_rtConent.Reset(); 70 m_rtStatic.Reset(); 71 } 72 CFWL_ListBoxImp::~CFWL_ListBoxImp() { 73 } 74 FWL_ERR CFWL_ListBoxImp::GetClassName(CFX_WideString& wsClass) const { 75 wsClass = FWL_CLASS_ListBox; 76 return FWL_ERR_Succeeded; 77 } 78 FX_DWORD CFWL_ListBoxImp::GetClassID() const { 79 return FWL_CLASSHASH_ListBox; 80 } 81 FWL_ERR CFWL_ListBoxImp::Initialize() { 82 if (CFWL_WidgetImp::Initialize() != FWL_ERR_Succeeded) 83 return FWL_ERR_Indefinite; 84 m_pDelegate = new CFWL_ListBoxImpDelegate(this); 85 return FWL_ERR_Succeeded; 86 } 87 FWL_ERR CFWL_ListBoxImp::Finalize() { 88 if (m_pVertScrollBar) { 89 m_pVertScrollBar->Finalize(); 90 } 91 if (m_pHorzScrollBar) { 92 m_pHorzScrollBar->Finalize(); 93 } 94 delete m_pDelegate; 95 m_pDelegate = nullptr; 96 return CFWL_WidgetImp::Finalize(); 97 } 98 FWL_ERR CFWL_ListBoxImp::GetWidgetRect(CFX_RectF& rect, FX_BOOL bAutoSize) { 99 if (bAutoSize) { 100 rect.Set(0, 0, 0, 0); 101 if (!m_pProperties->m_pThemeProvider) { 102 m_pProperties->m_pThemeProvider = GetAvailableTheme(); 103 } 104 CFX_SizeF fs = CalcSize(TRUE); 105 rect.Set(0, 0, fs.x, fs.y); 106 CFWL_WidgetImp::GetWidgetRect(rect, TRUE); 107 } else { 108 rect = m_pProperties->m_rtWidget; 109 } 110 return FWL_ERR_Succeeded; 111 } 112 FWL_ERR CFWL_ListBoxImp::Update() { 113 if (IsLocked()) { 114 return FWL_ERR_Indefinite; 115 } 116 if (!m_pProperties->m_pThemeProvider) { 117 m_pProperties->m_pThemeProvider = GetAvailableTheme(); 118 } 119 m_iTTOAligns = FDE_TTOALIGNMENT_Center; 120 switch (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_AlignMask) { 121 case FWL_STYLEEXT_LTB_LeftAlign: { 122 m_iTTOAligns = FDE_TTOALIGNMENT_CenterLeft; 123 break; 124 } 125 case FWL_STYLEEXT_LTB_RightAlign: { 126 m_iTTOAligns = FDE_TTOALIGNMENT_CenterRight; 127 break; 128 } 129 case FWL_STYLEEXT_LTB_CenterAlign: 130 default: { m_iTTOAligns = FDE_TTOALIGNMENT_Center; } 131 } 132 if (m_pProperties->m_dwStyleExes & FWL_WGTSTYLE_RTLReading) { 133 m_dwTTOStyles |= FDE_TTOSTYLE_RTL; 134 } 135 m_dwTTOStyles |= FDE_TTOSTYLE_SingleLine; 136 m_fScorllBarWidth = GetScrollWidth(); 137 SortItem(); 138 CalcSize(); 139 return FWL_ERR_Succeeded; 140 } 141 FX_DWORD CFWL_ListBoxImp::HitTest(FX_FLOAT fx, FX_FLOAT fy) { 142 if (IsShowScrollBar(FALSE)) { 143 CFX_RectF rect; 144 m_pHorzScrollBar->GetWidgetRect(rect); 145 if (rect.Contains(fx, fy)) { 146 return FWL_WGTHITTEST_HScrollBar; 147 } 148 } 149 if (IsShowScrollBar(TRUE)) { 150 CFX_RectF rect; 151 m_pVertScrollBar->GetWidgetRect(rect); 152 if (rect.Contains(fx, fy)) { 153 return FWL_WGTHITTEST_VScrollBar; 154 } 155 } 156 if (m_rtClient.Contains(fx, fy)) { 157 return FWL_WGTHITTEST_Client; 158 } 159 return FWL_WGTHITTEST_Unknown; 160 } 161 FWL_ERR CFWL_ListBoxImp::DrawWidget(CFX_Graphics* pGraphics, 162 const CFX_Matrix* pMatrix) { 163 if (!pGraphics) 164 return FWL_ERR_Indefinite; 165 if (!m_pProperties->m_pThemeProvider) 166 return FWL_ERR_Indefinite; 167 IFWL_ThemeProvider* pTheme = m_pProperties->m_pThemeProvider; 168 pGraphics->SaveGraphState(); 169 if (HasBorder()) { 170 DrawBorder(pGraphics, FWL_PART_LTB_Border, pTheme, pMatrix); 171 } 172 if (HasEdge()) { 173 DrawEdge(pGraphics, FWL_PART_LTB_Edge, pTheme, pMatrix); 174 } 175 CFX_RectF rtClip(m_rtConent); 176 if (IsShowScrollBar(FALSE)) { 177 rtClip.height -= m_fScorllBarWidth; 178 } 179 if (IsShowScrollBar(TRUE)) { 180 rtClip.width -= m_fScorllBarWidth; 181 } 182 if (pMatrix) { 183 pMatrix->TransformRect(rtClip); 184 } 185 pGraphics->SetClipRect(rtClip); 186 if ((m_pProperties->m_dwStyles & FWL_WGTSTYLE_NoBackground) == 0) { 187 DrawBkground(pGraphics, pTheme, pMatrix); 188 } 189 DrawItems(pGraphics, pTheme, pMatrix); 190 pGraphics->RestoreGraphState(); 191 return FWL_ERR_Succeeded; 192 } 193 FWL_ERR CFWL_ListBoxImp::SetThemeProvider(IFWL_ThemeProvider* pThemeProvider) { 194 if (!pThemeProvider) 195 return FWL_ERR_Indefinite; 196 if (!pThemeProvider->IsValidWidget(m_pInterface)) { 197 m_pScrollBarTP = pThemeProvider; 198 return FWL_ERR_Succeeded; 199 } 200 m_pProperties->m_pThemeProvider = pThemeProvider; 201 return FWL_ERR_Succeeded; 202 } 203 int32_t CFWL_ListBoxImp::CountSelItems() { 204 if (!m_pProperties->m_pDataProvider) 205 return 0; 206 int32_t iRet = 0; 207 IFWL_ListBoxDP* pData = 208 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 209 int32_t iCount = pData->CountItems(m_pInterface); 210 for (int32_t i = 0; i < iCount; i++) { 211 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 212 if (!hItem) { 213 continue; 214 } 215 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); 216 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { 217 iRet++; 218 } 219 } 220 return iRet; 221 } 222 FWL_HLISTITEM CFWL_ListBoxImp::GetSelItem(int32_t nIndexSel) { 223 if (!m_pProperties->m_pDataProvider) 224 return NULL; 225 int32_t index = 0; 226 IFWL_ListBoxDP* pData = 227 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 228 int32_t iCount = pData->CountItems(m_pInterface); 229 for (int32_t i = 0; i < iCount; i++) { 230 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 231 if (!hItem) { 232 return NULL; 233 } 234 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); 235 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { 236 if (index == nIndexSel) { 237 return hItem; 238 } else { 239 index++; 240 } 241 } 242 } 243 return NULL; 244 } 245 int32_t CFWL_ListBoxImp::GetSelIndex(int32_t nIndex) { 246 if (!m_pProperties->m_pDataProvider) 247 return -1; 248 int32_t index = 0; 249 IFWL_ListBoxDP* pData = 250 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 251 int32_t iCount = pData->CountItems(m_pInterface); 252 for (int32_t i = 0; i < iCount; i++) { 253 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 254 if (!hItem) { 255 return -1; 256 } 257 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); 258 if (dwStyle & FWL_ITEMSTATE_LTB_Selected) { 259 if (index == nIndex) { 260 return i; 261 } else { 262 index++; 263 } 264 } 265 } 266 return -1; 267 } 268 FWL_ERR CFWL_ListBoxImp::SetSelItem(FWL_HLISTITEM hItem, FX_BOOL bSelect) { 269 if (!m_pProperties->m_pDataProvider) 270 return FWL_ERR_Indefinite; 271 if (!hItem) { 272 if (bSelect) { 273 SelectAll(); 274 } else { 275 ClearSelection(); 276 SetFocusItem(NULL); 277 } 278 return FWL_ERR_Indefinite; 279 } 280 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection) { 281 SetSelectionDirect(hItem, bSelect); 282 } else { 283 SetSelection(hItem, hItem, bSelect); 284 } 285 return FWL_ERR_Succeeded; 286 } 287 FWL_ERR CFWL_ListBoxImp::GetItemText(FWL_HLISTITEM hItem, 288 CFX_WideString& wsText) { 289 if (!m_pProperties->m_pDataProvider) 290 return FWL_ERR_Indefinite; 291 IFWL_ListBoxDP* pData = 292 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 293 if (!hItem) 294 return FWL_ERR_Indefinite; 295 pData->GetItemText(m_pInterface, hItem, wsText); 296 return FWL_ERR_Succeeded; 297 } 298 FWL_ERR CFWL_ListBoxImp::GetScrollPos(FX_FLOAT& fPos, FX_BOOL bVert) { 299 if ((bVert && IsShowScrollBar(TRUE)) || (!bVert && IsShowScrollBar(FALSE))) { 300 IFWL_ScrollBar* pScrollBar = 301 bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get(); 302 fPos = pScrollBar->GetPos(); 303 return FWL_ERR_Succeeded; 304 } 305 return FWL_ERR_Indefinite; 306 } 307 FWL_ERR* CFWL_ListBoxImp::Sort(IFWL_ListBoxCompare* pCom) { 308 FWL_HLISTITEM hTemp; 309 IFWL_ListBoxDP* pData = 310 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 311 int32_t sz = pData->CountItems(m_pInterface); 312 for (int32_t i = 0; i < sz - 1; i++) { 313 for (int32_t j = i + 1; j < sz; j++) { 314 if (pCom->Compare(pData->GetItem(m_pInterface, i), 315 pData->GetItem(m_pInterface, j)) > 0) { 316 hTemp = pData->GetItem(m_pInterface, i); 317 pData->SetItemIndex(m_pInterface, pData->GetItem(m_pInterface, j), i); 318 pData->SetItemIndex(m_pInterface, hTemp, j); 319 } 320 } 321 } 322 return FWL_ERR_Succeeded; 323 } 324 FWL_HLISTITEM CFWL_ListBoxImp::GetItem(FWL_HLISTITEM hItem, 325 FX_DWORD dwKeyCode) { 326 FWL_HLISTITEM hRet = NULL; 327 switch (dwKeyCode) { 328 case FWL_VKEY_Up: 329 case FWL_VKEY_Down: 330 case FWL_VKEY_Home: 331 case FWL_VKEY_End: { 332 FX_BOOL bUp = dwKeyCode == FWL_VKEY_Up; 333 FX_BOOL bDown = dwKeyCode == FWL_VKEY_Down; 334 FX_BOOL bHome = dwKeyCode == FWL_VKEY_Home; 335 IFWL_ListBoxDP* pData = 336 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 337 int32_t iDstItem = -1; 338 if (bUp || bDown) { 339 int32_t index = pData->GetItemIndex(m_pInterface, hItem); 340 iDstItem = dwKeyCode == FWL_VKEY_Up ? index - 1 : index + 1; 341 } else if (bHome) { 342 iDstItem = 0; 343 } else { 344 int32_t iCount = pData->CountItems(m_pInterface); 345 iDstItem = iCount - 1; 346 } 347 hRet = pData->GetItem(m_pInterface, iDstItem); 348 break; 349 } 350 default: {} 351 } 352 return hRet; 353 } 354 void CFWL_ListBoxImp::SetSelection(FWL_HLISTITEM hStart, 355 FWL_HLISTITEM hEnd, 356 FX_BOOL bSelected) { 357 IFWL_ListBoxDP* pData = 358 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 359 int32_t iStart = pData->GetItemIndex(m_pInterface, hStart); 360 int32_t iEnd = pData->GetItemIndex(m_pInterface, hEnd); 361 if (iStart > iEnd) { 362 int32_t iTemp = iStart; 363 iStart = iEnd; 364 iEnd = iTemp; 365 } 366 if (bSelected) { 367 int32_t iCount = pData->CountItems(m_pInterface); 368 for (int32_t i = 0; i < iCount; i++) { 369 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 370 SetSelectionDirect(hItem, FALSE); 371 } 372 } 373 for (; iStart <= iEnd; iStart++) { 374 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, iStart); 375 SetSelectionDirect(hItem, bSelected); 376 } 377 } 378 void CFWL_ListBoxImp::SetSelectionDirect(FWL_HLISTITEM hItem, FX_BOOL bSelect) { 379 IFWL_ListBoxDP* pData = 380 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 381 FX_DWORD dwOldStyle = pData->GetItemStyles(m_pInterface, hItem); 382 bSelect ? dwOldStyle |= FWL_ITEMSTATE_LTB_Selected 383 : dwOldStyle &= ~FWL_ITEMSTATE_LTB_Selected; 384 pData->SetItemStyles(m_pInterface, hItem, dwOldStyle); 385 } 386 FX_BOOL CFWL_ListBoxImp::IsItemSelected(FWL_HLISTITEM hItem) { 387 IFWL_ListBoxDP* pData = 388 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 389 FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem); 390 return (dwState & FWL_ITEMSTATE_LTB_Selected) != 0; 391 } 392 void CFWL_ListBoxImp::ClearSelection() { 393 FX_BOOL bMulti = 394 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection; 395 IFWL_ListBoxDP* pData = 396 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 397 int32_t iCount = pData->CountItems(m_pInterface); 398 for (int32_t i = 0; i < iCount; i++) { 399 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 400 FX_DWORD dwState = pData->GetItemStyles(m_pInterface, hItem); 401 FX_BOOL bFindSel = dwState & FWL_ITEMSTATE_LTB_Selected; 402 if (!bFindSel) { 403 continue; 404 } 405 SetSelectionDirect(hItem, FALSE); 406 if (!bMulti) { 407 return; 408 } 409 } 410 } 411 void CFWL_ListBoxImp::SelectAll() { 412 FX_BOOL bMulti = 413 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiSelection; 414 if (!bMulti) { 415 return; 416 } 417 IFWL_ListBoxDP* pData = 418 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 419 int32_t iCount = pData->CountItems(m_pInterface); 420 if (iCount > 0) { 421 FWL_HLISTITEM hItemStart = pData->GetItem(m_pInterface, 0); 422 FWL_HLISTITEM hItemEnd = pData->GetItem(m_pInterface, iCount - 1); 423 SetSelection(hItemStart, hItemEnd, FALSE); 424 } 425 } 426 FWL_HLISTITEM CFWL_ListBoxImp::GetFocusedItem() { 427 IFWL_ListBoxDP* pData = 428 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 429 int32_t iCount = pData->CountItems(m_pInterface); 430 for (int32_t i = 0; i < iCount; i++) { 431 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 432 if (!hItem) 433 return NULL; 434 if (pData->GetItemStyles(m_pInterface, hItem) & FWL_ITEMSTATE_LTB_Focused) { 435 return hItem; 436 } 437 } 438 return NULL; 439 } 440 void CFWL_ListBoxImp::SetFocusItem(FWL_HLISTITEM hItem) { 441 IFWL_ListBoxDP* pData = 442 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 443 FWL_HLISTITEM hFocus = GetFocusedItem(); 444 if (hItem != hFocus) { 445 if (hFocus) { 446 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hFocus); 447 dwStyle &= ~FWL_ITEMSTATE_LTB_Focused; 448 pData->SetItemStyles(m_pInterface, hFocus, dwStyle); 449 } 450 if (hItem) { 451 FX_DWORD dwStyle = pData->GetItemStyles(m_pInterface, hItem); 452 dwStyle |= FWL_ITEMSTATE_LTB_Focused; 453 pData->SetItemStyles(m_pInterface, hItem, dwStyle); 454 } 455 } 456 } 457 FWL_HLISTITEM CFWL_ListBoxImp::GetItemAtPoint(FX_FLOAT fx, FX_FLOAT fy) { 458 fx -= m_rtConent.left, fy -= m_rtConent.top; 459 FX_FLOAT fPosX = 0.0f; 460 if (m_pHorzScrollBar) { 461 fPosX = m_pHorzScrollBar->GetPos(); 462 } 463 FX_FLOAT fPosY = 0.0; 464 if (m_pVertScrollBar) { 465 fPosY = m_pVertScrollBar->GetPos(); 466 } 467 IFWL_ListBoxDP* pData = 468 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 469 int32_t nCount = pData->CountItems(m_pInterface); 470 for (int32_t i = 0; i < nCount; i++) { 471 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 472 if (!hItem) { 473 continue; 474 } 475 CFX_RectF rtItem; 476 pData->GetItemRect(m_pInterface, hItem, rtItem); 477 rtItem.Offset(-fPosX, -fPosY); 478 if (rtItem.Contains(fx, fy)) { 479 return hItem; 480 } 481 } 482 return NULL; 483 } 484 FX_BOOL CFWL_ListBoxImp::GetItemCheckRect(FWL_HLISTITEM hItem, 485 CFX_RectF& rtCheck) { 486 if (!m_pProperties->m_pDataProvider) 487 return FALSE; 488 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { 489 return FALSE; 490 } 491 IFWL_ListBoxDP* pData = 492 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 493 pData->GetItemCheckRect(m_pInterface, hItem, rtCheck); 494 return TRUE; 495 } 496 FX_BOOL CFWL_ListBoxImp::GetItemChecked(FWL_HLISTITEM hItem) { 497 if (!m_pProperties->m_pDataProvider) 498 return FALSE; 499 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { 500 return FALSE; 501 } 502 IFWL_ListBoxDP* pData = 503 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 504 return (pData->GetItemCheckState(m_pInterface, hItem) & 505 FWL_ITEMSTATE_LTB_Checked); 506 } 507 FX_BOOL CFWL_ListBoxImp::SetItemChecked(FWL_HLISTITEM hItem, FX_BOOL bChecked) { 508 if (!m_pProperties->m_pDataProvider) 509 return FALSE; 510 if (!(m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check)) { 511 return FALSE; 512 } 513 IFWL_ListBoxDP* pData = 514 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 515 pData->SetItemCheckState(m_pInterface, hItem, 516 bChecked ? FWL_ITEMSTATE_LTB_Checked : 0); 517 return TRUE; 518 } 519 FX_BOOL CFWL_ListBoxImp::ScrollToVisible(FWL_HLISTITEM hItem) { 520 if (!m_pVertScrollBar) 521 return FALSE; 522 CFX_RectF rtItem; 523 IFWL_ListBoxDP* pData = 524 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 525 pData->GetItemRect(m_pInterface, hItem, rtItem); 526 FX_BOOL bScroll = FALSE; 527 FX_FLOAT fPosY = m_pVertScrollBar->GetPos(); 528 rtItem.Offset(0, -fPosY + m_rtConent.top); 529 if (rtItem.top < m_rtConent.top) { 530 fPosY += rtItem.top - m_rtConent.top; 531 bScroll = TRUE; 532 } else if (rtItem.bottom() > m_rtConent.bottom()) { 533 fPosY += rtItem.bottom() - m_rtConent.bottom(); 534 bScroll = TRUE; 535 } 536 if (!bScroll) { 537 return FALSE; 538 } 539 m_pVertScrollBar->SetPos(fPosY); 540 m_pVertScrollBar->SetTrackPos(fPosY); 541 Repaint(&m_rtClient); 542 return TRUE; 543 } 544 void CFWL_ListBoxImp::DrawBkground(CFX_Graphics* pGraphics, 545 IFWL_ThemeProvider* pTheme, 546 const CFX_Matrix* pMatrix) { 547 if (!pGraphics) 548 return; 549 if (!pTheme) 550 return; 551 CFWL_ThemeBackground param; 552 param.m_pWidget = m_pInterface; 553 param.m_iPart = FWL_PART_LTB_Background; 554 param.m_dwStates = 0; 555 param.m_pGraphics = pGraphics; 556 param.m_matrix.Concat(*pMatrix); 557 param.m_rtPart = m_rtClient; 558 if (IsShowScrollBar(FALSE) && IsShowScrollBar(TRUE)) { 559 param.m_pData = &m_rtStatic; 560 } 561 if (!IsEnabled()) { 562 param.m_dwStates = FWL_PARTSTATE_LTB_Disabled; 563 } 564 pTheme->DrawBackground(¶m); 565 } 566 void CFWL_ListBoxImp::DrawItems(CFX_Graphics* pGraphics, 567 IFWL_ThemeProvider* pTheme, 568 const CFX_Matrix* pMatrix) { 569 FX_FLOAT fPosX = 0.0f; 570 if (m_pHorzScrollBar) { 571 fPosX = m_pHorzScrollBar->GetPos(); 572 } 573 FX_FLOAT fPosY = 0.0f; 574 if (m_pVertScrollBar) { 575 fPosY = m_pVertScrollBar->GetPos(); 576 } 577 CFX_RectF rtView(m_rtConent); 578 if (m_pHorzScrollBar) { 579 rtView.height -= m_fScorllBarWidth; 580 } 581 if (m_pVertScrollBar) { 582 rtView.width -= m_fScorllBarWidth; 583 } 584 FX_BOOL bMultiCol = 585 m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn; 586 IFWL_ListBoxDP* pData = 587 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 588 int32_t iCount = pData->CountItems(m_pInterface); 589 for (int32_t i = 0; i < iCount; i++) { 590 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 591 if (!hItem) { 592 continue; 593 } 594 CFX_RectF rtItem; 595 pData->GetItemRect(m_pInterface, hItem, rtItem); 596 rtItem.Offset(m_rtConent.left - fPosX, m_rtConent.top - fPosY); 597 if (rtItem.bottom() < m_rtConent.top) { 598 continue; 599 } 600 if (rtItem.top >= m_rtConent.bottom()) { 601 break; 602 } 603 if (bMultiCol && rtItem.left > m_rtConent.right()) { 604 break; 605 } 606 if (GetStylesEx() & FWL_STYLEEXT_LTB_OwnerDraw) { 607 CFWL_EvtLtbDrawItem ev; 608 ev.m_pSrcTarget = m_pInterface; 609 ev.m_pGraphics = pGraphics; 610 ev.m_matrix = *pMatrix; 611 ev.m_index = i; 612 ev.m_rect = rtItem; 613 DispatchEvent(&ev); 614 } else { 615 DrawItem(pGraphics, pTheme, hItem, i, rtItem, pMatrix); 616 } 617 } 618 } 619 void CFWL_ListBoxImp::DrawItem(CFX_Graphics* pGraphics, 620 IFWL_ThemeProvider* pTheme, 621 FWL_HLISTITEM hItem, 622 int32_t Index, 623 const CFX_RectF& rtItem, 624 const CFX_Matrix* pMatrix) { 625 IFWL_ListBoxDP* pData = 626 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 627 FX_DWORD dwItemStyles = pData->GetItemStyles(m_pInterface, hItem); 628 FX_DWORD dwPartStates = FWL_PARTSTATE_LTB_Normal; 629 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Disabled) { 630 dwPartStates = FWL_PARTSTATE_LTB_Disabled; 631 } else if (dwItemStyles & FWL_ITEMSTATE_LTB_Selected) { 632 dwPartStates = FWL_PARTSTATE_LTB_Selected; 633 } 634 if (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused && 635 dwItemStyles & FWL_ITEMSTATE_LTB_Focused) { 636 dwPartStates |= FWL_PARTSTATE_LTB_Focused; 637 } 638 FWL_ListBoxItemData itemData; 639 itemData.pDataProvider = pData; 640 itemData.iIndex = Index; 641 { 642 CFWL_ThemeBackground param; 643 param.m_pWidget = m_pInterface; 644 param.m_iPart = FWL_PART_LTB_ListItem; 645 param.m_dwStates = dwPartStates; 646 param.m_pGraphics = pGraphics; 647 param.m_matrix.Concat(*pMatrix); 648 param.m_rtPart = rtItem; 649 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); 650 CFX_RectF rtFocus(rtItem); 651 param.m_pData = &rtFocus; 652 if (m_pVertScrollBar && !m_pHorzScrollBar && 653 (dwPartStates & FWL_PARTSTATE_LTB_Focused)) { 654 param.m_rtPart.left += 1; 655 param.m_rtPart.width -= (m_fScorllBarWidth + 1); 656 rtFocus.Deflate(0.5, 0.5, 1 + m_fScorllBarWidth, 1); 657 } 658 pTheme->DrawBackground(¶m); 659 } 660 { 661 FX_BOOL bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon; 662 if (bHasIcon) { 663 CFX_RectF rtDIB; 664 CFX_DIBitmap* pDib = pData->GetItemIcon(m_pInterface, hItem); 665 rtDIB.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height); 666 if (pDib) { 667 CFWL_ThemeBackground param; 668 param.m_pWidget = m_pInterface; 669 param.m_iPart = FWL_PART_LTB_Icon; 670 param.m_pGraphics = pGraphics; 671 param.m_matrix.Concat(*pMatrix); 672 param.m_rtPart = rtDIB; 673 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); 674 param.m_pImage = pDib; 675 pTheme->DrawBackground(¶m); 676 } 677 } 678 FX_BOOL bHasCheck = GetStylesEx() & FWL_STYLEEXT_LTB_Check; 679 if (bHasCheck) { 680 CFX_RectF rtCheck; 681 rtCheck.Set(rtItem.left, rtItem.top, rtItem.height, rtItem.height); 682 rtCheck.Deflate(2, 2, 2, 2); 683 pData->SetItemCheckRect(m_pInterface, hItem, rtCheck); 684 CFWL_ThemeBackground param; 685 param.m_pWidget = m_pInterface; 686 param.m_iPart = FWL_PART_LTB_Check; 687 param.m_pGraphics = pGraphics; 688 if (GetItemChecked(hItem)) { 689 param.m_dwStates = FWL_PARTSTATE_LTB_Checked; 690 } else { 691 param.m_dwStates = FWL_PARTSTATE_LTB_UnChecked; 692 } 693 param.m_matrix.Concat(*pMatrix); 694 param.m_rtPart = rtCheck; 695 param.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); 696 pTheme->DrawBackground(¶m); 697 } 698 CFX_WideString wsText; 699 pData->GetItemText(m_pInterface, hItem, wsText); 700 if (wsText.GetLength() <= 0) { 701 return; 702 } 703 CFX_RectF rtText(rtItem); 704 rtText.Deflate(FWL_LISTBOX_ItemTextMargin, FWL_LISTBOX_ItemTextMargin); 705 if (bHasIcon || bHasCheck) { 706 rtText.Deflate(rtItem.height, 0, 0, 0); 707 } 708 CFWL_ThemeText textParam; 709 textParam.m_pWidget = m_pInterface; 710 textParam.m_iPart = FWL_PART_LTB_ListItem; 711 textParam.m_dwStates = dwPartStates; 712 textParam.m_pGraphics = pGraphics; 713 textParam.m_matrix.Concat(*pMatrix); 714 textParam.m_rtPart = rtText; 715 textParam.m_wsText = wsText; 716 textParam.m_dwTTOStyles = m_dwTTOStyles; 717 textParam.m_iTTOAlign = m_iTTOAligns; 718 textParam.m_dwData = (FX_DWORD)(uintptr_t)(&itemData); 719 pTheme->DrawText(&textParam); 720 } 721 } 722 CFX_SizeF CFWL_ListBoxImp::CalcSize(FX_BOOL bAutoSize) { 723 CFX_SizeF fs; 724 fs.Set(0, 0); 725 if (!m_pProperties->m_pThemeProvider) 726 return fs; 727 GetClientRect(m_rtClient); 728 m_rtConent = m_rtClient; 729 CFX_RectF rtUIMargin; 730 rtUIMargin.Set(0, 0, 0, 0); 731 if (!m_pOuter) { 732 CFX_RectF* pUIMargin = 733 static_cast<CFX_RectF*>(GetThemeCapacity(FWL_WGTCAPACITY_UIMargin)); 734 if (pUIMargin) { 735 m_rtConent.Deflate(pUIMargin->left, pUIMargin->top, pUIMargin->width, 736 pUIMargin->height); 737 } 738 } 739 FX_FLOAT fWidth = 0; 740 if (m_pProperties->m_pThemeProvider->IsCustomizedLayout(m_pInterface)) { 741 IFWL_ListBoxDP* pData = 742 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 743 if (!bAutoSize) { 744 } 745 int32_t iCount = pData->CountItems(m_pInterface); 746 for (int32_t i = 0; i < iCount; i++) { 747 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 748 CFWL_ThemePart itemPart; 749 itemPart.m_pWidget = m_pInterface; 750 itemPart.m_iPart = FWL_PART_LTB_ListItem; 751 itemPart.m_pData = m_pProperties->m_pDataProvider; 752 itemPart.m_dwData = i; 753 CFX_RectF r; 754 m_pProperties->m_pThemeProvider->GetPartRect(&itemPart, r); 755 if (!bAutoSize) { 756 CFX_RectF rtItem; 757 rtItem.Set(m_rtClient.left, m_rtClient.top + fs.y, r.width, r.height); 758 IFWL_ListBoxDP* pData = 759 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 760 pData->SetItemRect(m_pInterface, hItem, rtItem); 761 } 762 fs.y += r.height; 763 if (fs.x < r.width) { 764 fs.x = r.width; 765 fWidth = r.width; 766 } 767 } 768 } else { 769 fWidth = GetMaxTextWidth(); 770 fWidth += 2 * FWL_LISTBOX_ItemTextMargin; 771 if (!bAutoSize) { 772 FX_FLOAT fActualWidth = 773 m_rtClient.width - rtUIMargin.left - rtUIMargin.width; 774 if (fWidth < fActualWidth) { 775 fWidth = fActualWidth; 776 } 777 } 778 IFWL_ListBoxDP* pData = 779 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 780 m_fItemHeight = GetItemHeigt(); 781 FX_BOOL bHasIcon; 782 bHasIcon = GetStylesEx() & FWL_STYLEEXT_LTB_Icon; 783 if (bHasIcon) { 784 fWidth += m_fItemHeight; 785 } 786 int32_t iCount = pData->CountItems(m_pInterface); 787 for (int32_t i = 0; i < iCount; i++) { 788 FWL_HLISTITEM htem = pData->GetItem(m_pInterface, i); 789 GetItemSize(fs, htem, fWidth, m_fItemHeight, bAutoSize); 790 } 791 } 792 if (bAutoSize) { 793 return fs; 794 } 795 FX_FLOAT iWidth = m_rtClient.width - rtUIMargin.left - rtUIMargin.width; 796 FX_FLOAT iHeight = m_rtClient.height; 797 FX_BOOL bShowVertScr = 798 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) && 799 (m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll); 800 FX_BOOL bShowHorzScr = 801 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarAlaways) && 802 (m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll); 803 if (!bShowVertScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_VScroll && 804 (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) == 0) { 805 bShowVertScr = (fs.y > iHeight); 806 } 807 if (!bShowHorzScr && m_pProperties->m_dwStyles & FWL_WGTSTYLE_HScroll) { 808 bShowHorzScr = (fs.x > iWidth); 809 } 810 CFX_SizeF szRange; 811 if (bShowVertScr) { 812 if (!m_pVertScrollBar) { 813 InitScrollBar(); 814 } 815 CFX_RectF rtScrollBar; 816 rtScrollBar.Set(m_rtClient.right() - m_fScorllBarWidth, m_rtClient.top, 817 m_fScorllBarWidth, m_rtClient.height - 1); 818 if (bShowHorzScr) { 819 rtScrollBar.height -= m_fScorllBarWidth; 820 } 821 m_pVertScrollBar->SetWidgetRect(rtScrollBar); 822 szRange.x = 0, szRange.y = fs.y - m_rtConent.height; 823 if (szRange.y < m_fItemHeight) { 824 szRange.y = m_fItemHeight; 825 } 826 m_pVertScrollBar->SetRange(szRange.x, szRange.y); 827 m_pVertScrollBar->SetPageSize(rtScrollBar.height * 9 / 10); 828 m_pVertScrollBar->SetStepSize(m_fItemHeight); 829 FX_FLOAT fPos = m_pVertScrollBar->GetPos(); 830 if (fPos < 0) { 831 fPos = 0; 832 } 833 if (fPos > szRange.y) { 834 fPos = szRange.y; 835 } 836 m_pVertScrollBar->SetPos(fPos); 837 m_pVertScrollBar->SetTrackPos(fPos); 838 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == 839 0 || 840 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) { 841 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); 842 } 843 m_pVertScrollBar->Update(); 844 } else if (m_pVertScrollBar) { 845 m_pVertScrollBar->SetPos(0); 846 m_pVertScrollBar->SetTrackPos(0); 847 m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); 848 } 849 if (bShowHorzScr) { 850 if (!m_pHorzScrollBar) { 851 InitScrollBar(FALSE); 852 } 853 CFX_RectF rtScrollBar; 854 rtScrollBar.Set(m_rtClient.left, m_rtClient.bottom() - m_fScorllBarWidth, 855 m_rtClient.width, m_fScorllBarWidth); 856 if (bShowVertScr) { 857 rtScrollBar.width -= m_fScorllBarWidth; 858 } 859 m_pHorzScrollBar->SetWidgetRect(rtScrollBar); 860 szRange.x = 0, szRange.y = fs.x - rtScrollBar.width; 861 m_pHorzScrollBar->SetRange(szRange.x, szRange.y); 862 m_pHorzScrollBar->SetPageSize(fWidth * 9 / 10); 863 m_pHorzScrollBar->SetStepSize(fWidth / 10); 864 FX_FLOAT fPos = m_pHorzScrollBar->GetPos(); 865 if (fPos < 0) { 866 fPos = 0; 867 } 868 if (fPos > szRange.y) { 869 fPos = szRange.y; 870 } 871 m_pHorzScrollBar->SetPos(fPos); 872 m_pHorzScrollBar->SetTrackPos(fPos); 873 if ((m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_ShowScrollBarFocus) == 874 0 || 875 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused)) { 876 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, FALSE); 877 } 878 m_pHorzScrollBar->Update(); 879 } else if (m_pHorzScrollBar) { 880 m_pHorzScrollBar->SetPos(0); 881 m_pHorzScrollBar->SetTrackPos(0); 882 m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, TRUE); 883 } 884 if (bShowVertScr && bShowHorzScr) { 885 m_rtStatic.Set(m_rtClient.right() - m_fScorllBarWidth, 886 m_rtClient.bottom() - m_fScorllBarWidth, m_fScorllBarWidth, 887 m_fScorllBarWidth); 888 } 889 return fs; 890 } 891 void CFWL_ListBoxImp::GetItemSize(CFX_SizeF& size, 892 FWL_HLISTITEM hItem, 893 FX_FLOAT fWidth, 894 FX_FLOAT m_fItemHeight, 895 FX_BOOL bAutoSize) { 896 if (m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_MultiColumn) { 897 } else { 898 if (!bAutoSize) { 899 CFX_RectF rtItem; 900 rtItem.Set(0, size.y, fWidth, m_fItemHeight); 901 IFWL_ListBoxDP* pData = 902 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 903 pData->SetItemRect(m_pInterface, hItem, rtItem); 904 } 905 size.x = fWidth; 906 size.y += m_fItemHeight; 907 } 908 } 909 FX_FLOAT CFWL_ListBoxImp::GetMaxTextWidth() { 910 FX_FLOAT fRet = 0.0f; 911 IFWL_ListBoxDP* pData = 912 static_cast<IFWL_ListBoxDP*>(m_pProperties->m_pDataProvider); 913 int32_t iCount = pData->CountItems(m_pInterface); 914 for (int32_t i = 0; i < iCount; i++) { 915 FWL_HLISTITEM hItem = pData->GetItem(m_pInterface, i); 916 if (!hItem) { 917 continue; 918 } 919 CFX_WideString wsText; 920 pData->GetItemText(m_pInterface, hItem, wsText); 921 CFX_SizeF sz = CalcTextSize(wsText, m_pProperties->m_pThemeProvider); 922 if (sz.x > fRet) { 923 fRet = sz.x; 924 } 925 } 926 return fRet; 927 } 928 FX_FLOAT CFWL_ListBoxImp::GetScrollWidth() { 929 FX_FLOAT* pfWidth = 930 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_ScrollBarWidth)); 931 if (!pfWidth) 932 return 0; 933 return *pfWidth; 934 } 935 FX_FLOAT CFWL_ListBoxImp::GetItemHeigt() { 936 FX_FLOAT* pfFont = 937 static_cast<FX_FLOAT*>(GetThemeCapacity(FWL_WGTCAPACITY_FontSize)); 938 if (!pfFont) 939 return 20; 940 return *pfFont + 2 * FWL_LISTBOX_ItemTextMargin; 941 } 942 void CFWL_ListBoxImp::InitScrollBar(FX_BOOL bVert) { 943 if ((bVert && m_pVertScrollBar) || (!bVert && m_pHorzScrollBar)) { 944 return; 945 } 946 CFWL_WidgetImpProperties prop; 947 prop.m_dwStyleExes = bVert ? FWL_STYLEEXT_SCB_Vert : FWL_STYLEEXT_SCB_Horz; 948 prop.m_dwStates = FWL_WGTSTATE_Invisible; 949 prop.m_pParent = m_pInterface; 950 prop.m_pThemeProvider = m_pScrollBarTP; 951 IFWL_ScrollBar* pScrollBar = IFWL_ScrollBar::Create(prop, m_pInterface); 952 pScrollBar->Initialize(); 953 (bVert ? &m_pVertScrollBar : &m_pHorzScrollBar)->reset(pScrollBar); 954 } 955 void CFWL_ListBoxImp::SortItem() {} 956 FX_BOOL CFWL_ListBoxImp::IsShowScrollBar(FX_BOOL bVert) { 957 IFWL_ScrollBar* pScrollbar = 958 bVert ? m_pVertScrollBar.get() : m_pHorzScrollBar.get(); 959 if (!pScrollbar || (pScrollbar->GetStates() & FWL_WGTSTATE_Invisible)) { 960 return FALSE; 961 } 962 return !(m_pProperties->m_dwStyleExes & 963 FWL_STYLEEXT_LTB_ShowScrollBarFocus) || 964 (m_pProperties->m_dwStates & FWL_WGTSTATE_Focused); 965 } 966 void CFWL_ListBoxImp::ProcessSelChanged() { 967 CFWL_EvtLtbSelChanged selEvent; 968 selEvent.m_pSrcTarget = m_pInterface; 969 CFX_Int32Array arrSels; 970 int32_t iCount = CountSelItems(); 971 for (int32_t i = 0; i < iCount; i++) { 972 FWL_HLISTITEM item = GetSelItem(i); 973 if (item == NULL) { 974 continue; 975 } 976 selEvent.iarraySels.Add(i); 977 } 978 DispatchEvent(&selEvent); 979 } 980 CFWL_ListBoxImpDelegate::CFWL_ListBoxImpDelegate(CFWL_ListBoxImp* pOwner) 981 : m_pOwner(pOwner) {} 982 int32_t CFWL_ListBoxImpDelegate::OnProcessMessage(CFWL_Message* pMessage) { 983 if (!pMessage) 984 return 0; 985 if (!m_pOwner->IsEnabled()) { 986 return 1; 987 } 988 FX_DWORD dwMsgCode = pMessage->GetClassID(); 989 int32_t iRet = 1; 990 switch (dwMsgCode) { 991 case FWL_MSGHASH_SetFocus: 992 case FWL_MSGHASH_KillFocus: { 993 OnFocusChanged(pMessage, dwMsgCode == FWL_MSGHASH_SetFocus); 994 break; 995 } 996 case FWL_MSGHASH_Mouse: { 997 CFWL_MsgMouse* pMsg = static_cast<CFWL_MsgMouse*>(pMessage); 998 FX_DWORD dwCmd = pMsg->m_dwCmd; 999 switch (dwCmd) { 1000 case FWL_MSGMOUSECMD_LButtonDown: { 1001 OnLButtonDown(pMsg); 1002 break; 1003 } 1004 case FWL_MSGMOUSECMD_LButtonUp: { 1005 OnLButtonUp(pMsg); 1006 break; 1007 } 1008 default: {} 1009 } 1010 break; 1011 } 1012 case FWL_MSGHASH_MouseWheel: { 1013 OnMouseWheel(static_cast<CFWL_MsgMouseWheel*>(pMessage)); 1014 break; 1015 } 1016 case FWL_MSGHASH_Key: { 1017 CFWL_MsgKey* pMsg = static_cast<CFWL_MsgKey*>(pMessage); 1018 if (pMsg->m_dwCmd == FWL_MSGKEYCMD_KeyDown) 1019 OnKeyDown(pMsg); 1020 break; 1021 } 1022 default: { iRet = 0; } 1023 } 1024 CFWL_WidgetImpDelegate::OnProcessMessage(pMessage); 1025 return iRet; 1026 } 1027 FWL_ERR CFWL_ListBoxImpDelegate::OnProcessEvent(CFWL_Event* pEvent) { 1028 if (!pEvent) 1029 return FWL_ERR_Indefinite; 1030 if (pEvent->GetClassID() != FWL_EVTHASH_Scroll) { 1031 return FWL_ERR_Succeeded; 1032 } 1033 IFWL_Widget* pSrcTarget = pEvent->m_pSrcTarget; 1034 if ((pSrcTarget == m_pOwner->m_pVertScrollBar.get() && 1035 m_pOwner->m_pVertScrollBar) || 1036 (pSrcTarget == m_pOwner->m_pHorzScrollBar.get() && 1037 m_pOwner->m_pHorzScrollBar)) { 1038 CFWL_EvtScroll* pScrollEvent = static_cast<CFWL_EvtScroll*>(pEvent); 1039 OnScroll(static_cast<IFWL_ScrollBar*>(pSrcTarget), 1040 pScrollEvent->m_iScrollCode, pScrollEvent->m_fPos); 1041 } 1042 return FWL_ERR_Succeeded; 1043 } 1044 FWL_ERR CFWL_ListBoxImpDelegate::OnDrawWidget(CFX_Graphics* pGraphics, 1045 const CFX_Matrix* pMatrix) { 1046 return m_pOwner->DrawWidget(pGraphics, pMatrix); 1047 } 1048 void CFWL_ListBoxImpDelegate::OnFocusChanged(CFWL_Message* pMsg, FX_BOOL bSet) { 1049 if (m_pOwner->GetStylesEx() & FWL_STYLEEXT_LTB_ShowScrollBarFocus) { 1050 if (m_pOwner->m_pVertScrollBar) { 1051 m_pOwner->m_pVertScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet); 1052 } 1053 if (m_pOwner->m_pHorzScrollBar) { 1054 m_pOwner->m_pHorzScrollBar->SetStates(FWL_WGTSTATE_Invisible, !bSet); 1055 } 1056 } 1057 if (bSet) { 1058 m_pOwner->m_pProperties->m_dwStates |= (FWL_WGTSTATE_Focused); 1059 } else { 1060 m_pOwner->m_pProperties->m_dwStates &= ~(FWL_WGTSTATE_Focused); 1061 } 1062 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1063 } 1064 void CFWL_ListBoxImpDelegate::OnLButtonDown(CFWL_MsgMouse* pMsg) { 1065 m_pOwner->m_bLButtonDown = TRUE; 1066 if ((m_pOwner->m_pProperties->m_dwStates & FWL_WGTSTATE_Focused) == 0) { 1067 m_pOwner->SetFocus(TRUE); 1068 } 1069 FWL_HLISTITEM hItem = m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); 1070 if (!hItem) { 1071 return; 1072 } 1073 if (m_pOwner->m_pProperties->m_dwStyleExes & 1074 FWL_STYLEEXT_LTB_MultiSelection) { 1075 if (pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl) { 1076 FX_BOOL bSelected = m_pOwner->IsItemSelected(hItem); 1077 m_pOwner->SetSelectionDirect(hItem, !bSelected); 1078 m_pOwner->m_hAnchor = hItem; 1079 } else if (pMsg->m_dwFlags & FWL_KEYFLAG_Shift) { 1080 if (m_pOwner->m_hAnchor) { 1081 m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE); 1082 } else { 1083 m_pOwner->SetSelectionDirect(hItem, TRUE); 1084 } 1085 } else { 1086 m_pOwner->SetSelection(hItem, hItem, TRUE); 1087 m_pOwner->m_hAnchor = hItem; 1088 } 1089 } else { 1090 m_pOwner->SetSelection(hItem, hItem, TRUE); 1091 } 1092 if (m_pOwner->m_pProperties->m_dwStyleExes & FWL_STYLEEXT_LTB_Check) { 1093 FWL_HLISTITEM hSelectedItem = 1094 m_pOwner->GetItemAtPoint(pMsg->m_fx, pMsg->m_fy); 1095 CFX_RectF rtCheck; 1096 m_pOwner->GetItemCheckRect(hSelectedItem, rtCheck); 1097 FX_BOOL bChecked = m_pOwner->GetItemChecked(hItem); 1098 if (rtCheck.Contains(pMsg->m_fx, pMsg->m_fy)) { 1099 if (bChecked) { 1100 m_pOwner->SetItemChecked(hItem, FALSE); 1101 } else { 1102 m_pOwner->SetItemChecked(hItem, TRUE); 1103 } 1104 m_pOwner->Update(); 1105 } 1106 } 1107 m_pOwner->SetFocusItem(hItem); 1108 m_pOwner->ScrollToVisible(hItem); 1109 m_pOwner->SetGrab(TRUE); 1110 m_pOwner->ProcessSelChanged(); 1111 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1112 } 1113 void CFWL_ListBoxImpDelegate::OnLButtonUp(CFWL_MsgMouse* pMsg) { 1114 if (m_pOwner->m_bLButtonDown) { 1115 m_pOwner->m_bLButtonDown = FALSE; 1116 m_pOwner->SetGrab(FALSE); 1117 DispatchSelChangedEv(); 1118 } 1119 } 1120 void CFWL_ListBoxImpDelegate::OnMouseWheel(CFWL_MsgMouseWheel* pMsg) { 1121 if (!m_pOwner->IsShowScrollBar(TRUE)) { 1122 return; 1123 } 1124 IFWL_WidgetDelegate* pDelegate = 1125 m_pOwner->m_pVertScrollBar->SetDelegate(NULL); 1126 pDelegate->OnProcessMessage(pMsg); 1127 } 1128 void CFWL_ListBoxImpDelegate::OnKeyDown(CFWL_MsgKey* pMsg) { 1129 FX_DWORD dwKeyCode = pMsg->m_dwKeyCode; 1130 switch (dwKeyCode) { 1131 case FWL_VKEY_Tab: 1132 case FWL_VKEY_Up: 1133 case FWL_VKEY_Down: 1134 case FWL_VKEY_Home: 1135 case FWL_VKEY_End: { 1136 FWL_HLISTITEM hItem = m_pOwner->GetFocusedItem(); 1137 hItem = m_pOwner->GetItem(hItem, dwKeyCode); 1138 FX_BOOL bShift = pMsg->m_dwFlags & FWL_KEYFLAG_Shift; 1139 FX_BOOL bCtrl = pMsg->m_dwFlags & FWL_KEYFLAG_Ctrl; 1140 OnVK(hItem, bShift, bCtrl); 1141 DispatchSelChangedEv(); 1142 m_pOwner->ProcessSelChanged(); 1143 break; 1144 } 1145 default: {} 1146 } 1147 } 1148 void CFWL_ListBoxImpDelegate::OnVK(FWL_HLISTITEM hItem, 1149 FX_BOOL bShift, 1150 FX_BOOL bCtrl) { 1151 if (!hItem) { 1152 return; 1153 } 1154 if (m_pOwner->m_pProperties->m_dwStyleExes & 1155 FWL_STYLEEXT_LTB_MultiSelection) { 1156 if (bCtrl) { 1157 } else if (bShift) { 1158 if (m_pOwner->m_hAnchor) { 1159 m_pOwner->SetSelection(m_pOwner->m_hAnchor, hItem, TRUE); 1160 } else { 1161 m_pOwner->SetSelectionDirect(hItem, TRUE); 1162 } 1163 } else { 1164 m_pOwner->SetSelection(hItem, hItem, TRUE); 1165 m_pOwner->m_hAnchor = hItem; 1166 } 1167 } else { 1168 m_pOwner->SetSelection(hItem, hItem, TRUE); 1169 } 1170 m_pOwner->SetFocusItem(hItem); 1171 m_pOwner->ScrollToVisible(hItem); 1172 { 1173 CFX_RectF rtInvalidate; 1174 rtInvalidate.Set(0, 0, m_pOwner->m_pProperties->m_rtWidget.width, 1175 m_pOwner->m_pProperties->m_rtWidget.height); 1176 m_pOwner->Repaint(&rtInvalidate); 1177 } 1178 } 1179 FX_BOOL CFWL_ListBoxImpDelegate::OnScroll(IFWL_ScrollBar* pScrollBar, 1180 FX_DWORD dwCode, 1181 FX_FLOAT fPos) { 1182 CFX_SizeF fs; 1183 pScrollBar->GetRange(fs.x, fs.y); 1184 FX_FLOAT iCurPos = pScrollBar->GetPos(); 1185 FX_FLOAT fStep = pScrollBar->GetStepSize(); 1186 switch (dwCode) { 1187 case FWL_SCBCODE_Min: { 1188 fPos = fs.x; 1189 break; 1190 } 1191 case FWL_SCBCODE_Max: { 1192 fPos = fs.y; 1193 break; 1194 } 1195 case FWL_SCBCODE_StepBackward: { 1196 fPos -= fStep; 1197 if (fPos < fs.x + fStep / 2) { 1198 fPos = fs.x; 1199 } 1200 break; 1201 } 1202 case FWL_SCBCODE_StepForward: { 1203 fPos += fStep; 1204 if (fPos > fs.y - fStep / 2) { 1205 fPos = fs.y; 1206 } 1207 break; 1208 } 1209 case FWL_SCBCODE_PageBackward: { 1210 fPos -= pScrollBar->GetPageSize(); 1211 if (fPos < fs.x) { 1212 fPos = fs.x; 1213 } 1214 break; 1215 } 1216 case FWL_SCBCODE_PageForward: { 1217 fPos += pScrollBar->GetPageSize(); 1218 if (fPos > fs.y) { 1219 fPos = fs.y; 1220 } 1221 break; 1222 } 1223 case FWL_SCBCODE_Pos: 1224 case FWL_SCBCODE_TrackPos: 1225 break; 1226 case FWL_SCBCODE_EndScroll: 1227 return FALSE; 1228 } 1229 if (iCurPos != fPos) { 1230 pScrollBar->SetPos(fPos); 1231 pScrollBar->SetTrackPos(fPos); 1232 m_pOwner->Repaint(&m_pOwner->m_rtClient); 1233 } 1234 return TRUE; 1235 } 1236 void CFWL_ListBoxImpDelegate::DispatchSelChangedEv() { 1237 CFWL_EvtLtbSelChanged ev; 1238 ev.m_pSrcTarget = m_pOwner->m_pInterface; 1239 m_pOwner->DispatchEvent(&ev); 1240 } 1241