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 "fpdfsdk/include/fxedit/fxet_edit.h" 8 #include "fpdfsdk/include/fxedit/fxet_list.h" 9 10 CFX_ListItem::CFX_ListItem() 11 : m_pEdit(NULL), 12 m_bSelected(FALSE), 13 m_bCaret(FALSE), 14 m_rcListItem(0.0f, 0.0f, 0.0f, 0.0f) { 15 m_pEdit = IFX_Edit::NewEdit(); 16 m_pEdit->SetAlignmentV(1); 17 m_pEdit->Initialize(); 18 } 19 20 CFX_ListItem::~CFX_ListItem() { 21 IFX_Edit::DelEdit(m_pEdit); 22 } 23 24 void CFX_ListItem::SetFontMap(IFX_Edit_FontMap* pFontMap) { 25 if (m_pEdit) 26 m_pEdit->SetFontMap(pFontMap); 27 } 28 29 IFX_Edit* CFX_ListItem::GetEdit() const { 30 return m_pEdit; 31 } 32 33 IFX_Edit_Iterator* CFX_ListItem::GetIterator() const { 34 if (m_pEdit) 35 return m_pEdit->GetIterator(); 36 37 return NULL; 38 } 39 40 void CFX_ListItem::SetRect(const CLST_Rect& rect) { 41 m_rcListItem = rect; 42 } 43 44 CLST_Rect CFX_ListItem::GetRect() const { 45 return m_rcListItem; 46 } 47 48 FX_BOOL CFX_ListItem::IsSelected() const { 49 return m_bSelected; 50 } 51 52 void CFX_ListItem::SetSelect(FX_BOOL bSelected) { 53 m_bSelected = bSelected; 54 } 55 56 FX_BOOL CFX_ListItem::IsCaret() const { 57 return m_bCaret; 58 } 59 60 void CFX_ListItem::SetCaret(FX_BOOL bCaret) { 61 m_bCaret = bCaret; 62 } 63 64 void CFX_ListItem::SetText(const FX_WCHAR* text) { 65 if (m_pEdit) 66 m_pEdit->SetText(text); 67 } 68 69 void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) { 70 if (m_pEdit) 71 m_pEdit->SetFontSize(fFontSize); 72 } 73 74 FX_FLOAT CFX_ListItem::GetItemHeight() const { 75 if (m_pEdit) 76 return m_pEdit->GetContentRect().Height(); 77 78 return 0.0f; 79 } 80 81 FX_WORD CFX_ListItem::GetFirstChar() const { 82 CPVT_Word word; 83 84 if (IFX_Edit_Iterator* pIterator = GetIterator()) { 85 pIterator->SetAt(1); 86 pIterator->GetWord(word); 87 } 88 89 return word.Word; 90 } 91 92 CFX_WideString CFX_ListItem::GetText() const { 93 if (m_pEdit) 94 return m_pEdit->GetText(); 95 96 return L""; 97 } 98 99 CFX_List::CFX_List() 100 : m_fFontSize(0.0f), m_pFontMap(NULL), m_bMultiple(FALSE) {} 101 102 CFX_List::~CFX_List() { 103 Empty(); 104 } 105 106 void CFX_List::Empty() { 107 for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) 108 delete m_aListItems.GetAt(i); 109 110 m_aListItems.RemoveAll(); 111 } 112 113 void CFX_List::SetFontMap(IFX_Edit_FontMap* pFontMap) { 114 m_pFontMap = pFontMap; 115 } 116 117 void CFX_List::SetFontSize(FX_FLOAT fFontSize) { 118 m_fFontSize = fFontSize; 119 } 120 121 void CFX_List::AddItem(const FX_WCHAR* str) { 122 CFX_ListItem* pListItem = new CFX_ListItem(); 123 pListItem->SetFontMap(m_pFontMap); 124 pListItem->SetFontSize(m_fFontSize); 125 pListItem->SetText(str); 126 m_aListItems.Add(pListItem); 127 } 128 129 void CFX_List::ReArrange(int32_t nItemIndex) { 130 FX_FLOAT fPosY = 0.0f; 131 132 if (CFX_ListItem* pPrevItem = m_aListItems.GetAt(nItemIndex - 1)) 133 fPosY = pPrevItem->GetRect().bottom; 134 135 for (int32_t i = nItemIndex, sz = m_aListItems.GetSize(); i < sz; i++) { 136 if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { 137 FX_FLOAT fListItemHeight = pListItem->GetItemHeight(); 138 pListItem->SetRect(CLST_Rect(0.0f, fPosY, 0.0f, fPosY + fListItemHeight)); 139 fPosY += fListItemHeight; 140 } 141 } 142 143 SetContentRect(CLST_Rect(0.0f, 0.0f, 0.0f, fPosY)); 144 } 145 146 IFX_Edit* CFX_List::GetItemEdit(int32_t nIndex) const { 147 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { 148 return pListItem->GetEdit(); 149 } 150 151 return NULL; 152 } 153 154 int32_t CFX_List::GetCount() const { 155 return m_aListItems.GetSize(); 156 } 157 158 CPDF_Rect CFX_List::GetPlateRect() const { 159 return CFX_ListContainer::GetPlateRect(); 160 } 161 162 CPDF_Rect CFX_List::GetContentRect() const { 163 return InnerToOuter(CFX_ListContainer::GetContentRect()); 164 } 165 166 FX_FLOAT CFX_List::GetFontSize() const { 167 return m_fFontSize; 168 } 169 170 int32_t CFX_List::GetItemIndex(const CPDF_Point& point) const { 171 CPDF_Point pt = OuterToInner(point); 172 173 FX_BOOL bFirst = TRUE; 174 FX_BOOL bLast = TRUE; 175 176 for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { 177 if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { 178 CLST_Rect rcListItem = pListItem->GetRect(); 179 180 if (FX_EDIT_IsFloatBigger(pt.y, rcListItem.top)) { 181 bFirst = FALSE; 182 } 183 184 if (FX_EDIT_IsFloatSmaller(pt.y, rcListItem.bottom)) { 185 bLast = FALSE; 186 } 187 188 if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) { 189 return i; 190 } 191 } 192 } 193 194 if (bFirst) 195 return 0; 196 if (bLast) 197 return m_aListItems.GetSize() - 1; 198 199 return -1; 200 } 201 202 FX_FLOAT CFX_List::GetFirstHeight() const { 203 if (CFX_ListItem* pListItem = m_aListItems.GetAt(0)) { 204 return pListItem->GetItemHeight(); 205 } 206 207 return 1.0f; 208 } 209 210 int32_t CFX_List::GetFirstSelected() const { 211 for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { 212 if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { 213 if (pListItem->IsSelected()) 214 return i; 215 } 216 } 217 return -1; 218 } 219 220 int32_t CFX_List::GetLastSelected() const { 221 for (int32_t i = m_aListItems.GetSize() - 1; i >= 0; i--) { 222 if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { 223 if (pListItem->IsSelected()) 224 return i; 225 } 226 } 227 return -1; 228 } 229 230 FX_WCHAR CFX_List::Toupper(FX_WCHAR c) const { 231 if ((c >= 'a') && (c <= 'z')) 232 c = c - ('a' - 'A'); 233 return c; 234 } 235 236 int32_t CFX_List::FindNext(int32_t nIndex, FX_WCHAR nChar) const { 237 int32_t nCircleIndex = nIndex; 238 239 for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { 240 nCircleIndex++; 241 if (nCircleIndex >= sz) 242 nCircleIndex = 0; 243 244 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nCircleIndex)) { 245 if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar)) 246 return nCircleIndex; 247 } 248 } 249 250 return nCircleIndex; 251 } 252 253 CPDF_Rect CFX_List::GetItemRect(int32_t nIndex) const { 254 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { 255 CPDF_Rect rcItem = pListItem->GetRect(); 256 rcItem.left = 0.0f; 257 rcItem.right = GetPlateRect().Width(); 258 return InnerToOuter(rcItem); 259 } 260 261 return CPDF_Rect(); 262 } 263 264 FX_BOOL CFX_List::IsItemSelected(int32_t nIndex) const { 265 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { 266 return pListItem->IsSelected(); 267 } 268 269 return FALSE; 270 } 271 272 void CFX_List::SetItemSelect(int32_t nItemIndex, FX_BOOL bSelected) { 273 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) { 274 pListItem->SetSelect(bSelected); 275 } 276 } 277 278 void CFX_List::SetItemCaret(int32_t nItemIndex, FX_BOOL bCaret) { 279 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) { 280 pListItem->SetCaret(bCaret); 281 } 282 } 283 284 void CFX_List::SetMultipleSel(FX_BOOL bMultiple) { 285 m_bMultiple = bMultiple; 286 } 287 288 FX_BOOL CFX_List::IsMultipleSel() const { 289 return m_bMultiple; 290 } 291 292 FX_BOOL CFX_List::IsValid(int32_t nItemIndex) const { 293 return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize(); 294 } 295 296 CFX_WideString CFX_List::GetItemText(int32_t nIndex) const { 297 if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { 298 return pListItem->GetText(); 299 } 300 301 return L""; 302 } 303 304 CPLST_Select::CPLST_Select() {} 305 306 CPLST_Select::~CPLST_Select() { 307 for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) 308 delete m_aItems.GetAt(i); 309 310 m_aItems.RemoveAll(); 311 } 312 313 void CPLST_Select::Add(int32_t nItemIndex) { 314 int32_t nIndex = Find(nItemIndex); 315 316 if (nIndex < 0) { 317 m_aItems.Add(new CPLST_Select_Item(nItemIndex, 1)); 318 } else { 319 if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) { 320 pItem->nState = 1; 321 } 322 } 323 } 324 325 void CPLST_Select::Add(int32_t nBeginIndex, int32_t nEndIndex) { 326 if (nBeginIndex > nEndIndex) { 327 int32_t nTemp = nEndIndex; 328 nEndIndex = nBeginIndex; 329 nBeginIndex = nTemp; 330 } 331 332 for (int32_t i = nBeginIndex; i <= nEndIndex; i++) 333 Add(i); 334 } 335 336 void CPLST_Select::Sub(int32_t nItemIndex) { 337 for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) { 338 if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) 339 if (pItem->nItemIndex == nItemIndex) 340 pItem->nState = -1; 341 } 342 } 343 344 void CPLST_Select::Sub(int32_t nBeginIndex, int32_t nEndIndex) { 345 if (nBeginIndex > nEndIndex) { 346 int32_t nTemp = nEndIndex; 347 nEndIndex = nBeginIndex; 348 nBeginIndex = nTemp; 349 } 350 351 for (int32_t i = nBeginIndex; i <= nEndIndex; i++) 352 Sub(i); 353 } 354 355 int32_t CPLST_Select::Find(int32_t nItemIndex) const { 356 for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) { 357 if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { 358 if (pItem->nItemIndex == nItemIndex) 359 return i; 360 } 361 } 362 363 return -1; 364 } 365 366 FX_BOOL CPLST_Select::IsExist(int32_t nItemIndex) const { 367 return Find(nItemIndex) >= 0; 368 } 369 370 int32_t CPLST_Select::GetCount() const { 371 return m_aItems.GetSize(); 372 } 373 374 int32_t CPLST_Select::GetItemIndex(int32_t nIndex) const { 375 if (nIndex >= 0 && nIndex < m_aItems.GetSize()) 376 if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) 377 return pItem->nItemIndex; 378 379 return -1; 380 } 381 382 int32_t CPLST_Select::GetState(int32_t nIndex) const { 383 if (nIndex >= 0 && nIndex < m_aItems.GetSize()) 384 if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) 385 return pItem->nState; 386 387 return 0; 388 } 389 390 void CPLST_Select::DeselectAll() { 391 for (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) { 392 if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { 393 pItem->nState = -1; 394 } 395 } 396 } 397 398 void CPLST_Select::Done() { 399 for (int32_t i = m_aItems.GetSize() - 1; i >= 0; i--) { 400 if (CPLST_Select_Item* pItem = m_aItems.GetAt(i)) { 401 if (pItem->nState == -1) { 402 delete pItem; 403 m_aItems.RemoveAt(i); 404 } else { 405 pItem->nState = 0; 406 } 407 } 408 } 409 } 410 411 CFX_ListCtrl::CFX_ListCtrl() 412 : m_pNotify(NULL), 413 m_bNotifyFlag(FALSE), 414 m_ptScrollPos(0.0f, 0.0f), 415 m_nSelItem(-1), 416 m_nFootIndex(-1), 417 m_bCtrlSel(FALSE), 418 m_nCaretIndex(-1) {} 419 420 CFX_ListCtrl::~CFX_ListCtrl() {} 421 422 void CFX_ListCtrl::SetNotify(IFX_List_Notify* pNotify) { 423 m_pNotify = pNotify; 424 } 425 426 CPDF_Point CFX_ListCtrl::InToOut(const CPDF_Point& point) const { 427 CPDF_Rect rcPlate = GetPlateRect(); 428 429 return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left), 430 point.y - (m_ptScrollPos.y - rcPlate.top)); 431 } 432 433 CPDF_Point CFX_ListCtrl::OutToIn(const CPDF_Point& point) const { 434 CPDF_Rect rcPlate = GetPlateRect(); 435 436 return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left), 437 point.y + (m_ptScrollPos.y - rcPlate.top)); 438 } 439 440 CPDF_Rect CFX_ListCtrl::InToOut(const CPDF_Rect& rect) const { 441 CPDF_Point ptLeftBottom = InToOut(CPDF_Point(rect.left, rect.bottom)); 442 CPDF_Point ptRightTop = InToOut(CPDF_Point(rect.right, rect.top)); 443 444 return CPDF_Rect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, ptRightTop.y); 445 } 446 447 CPDF_Rect CFX_ListCtrl::OutToIn(const CPDF_Rect& rect) const { 448 CPDF_Point ptLeftBottom = OutToIn(CPDF_Point(rect.left, rect.bottom)); 449 CPDF_Point ptRightTop = OutToIn(CPDF_Point(rect.right, rect.top)); 450 451 return CPDF_Rect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x, ptRightTop.y); 452 } 453 454 void CFX_ListCtrl::OnMouseDown(const CPDF_Point& point, 455 FX_BOOL bShift, 456 FX_BOOL bCtrl) { 457 int32_t nHitIndex = GetItemIndex(point); 458 459 if (IsMultipleSel()) { 460 if (bCtrl) { 461 if (IsItemSelected(nHitIndex)) { 462 m_aSelItems.Sub(nHitIndex); 463 SelectItems(); 464 m_bCtrlSel = FALSE; 465 } else { 466 m_aSelItems.Add(nHitIndex); 467 SelectItems(); 468 m_bCtrlSel = TRUE; 469 } 470 471 m_nFootIndex = nHitIndex; 472 } else if (bShift) { 473 m_aSelItems.DeselectAll(); 474 m_aSelItems.Add(m_nFootIndex, nHitIndex); 475 SelectItems(); 476 } else { 477 m_aSelItems.DeselectAll(); 478 m_aSelItems.Add(nHitIndex); 479 SelectItems(); 480 481 m_nFootIndex = nHitIndex; 482 } 483 484 SetCaret(nHitIndex); 485 } else { 486 SetSingleSelect(nHitIndex); 487 } 488 489 if (!IsItemVisible(nHitIndex)) 490 ScrollToListItem(nHitIndex); 491 } 492 493 void CFX_ListCtrl::OnMouseMove(const CPDF_Point& point, 494 FX_BOOL bShift, 495 FX_BOOL bCtrl) { 496 int32_t nHitIndex = GetItemIndex(point); 497 498 if (IsMultipleSel()) { 499 if (bCtrl) { 500 if (m_bCtrlSel) 501 m_aSelItems.Add(m_nFootIndex, nHitIndex); 502 else 503 m_aSelItems.Sub(m_nFootIndex, nHitIndex); 504 505 SelectItems(); 506 } else { 507 m_aSelItems.DeselectAll(); 508 m_aSelItems.Add(m_nFootIndex, nHitIndex); 509 SelectItems(); 510 } 511 512 SetCaret(nHitIndex); 513 } else { 514 SetSingleSelect(nHitIndex); 515 } 516 517 if (!IsItemVisible(nHitIndex)) 518 ScrollToListItem(nHitIndex); 519 } 520 521 void CFX_ListCtrl::OnVK(int32_t nItemIndex, FX_BOOL bShift, FX_BOOL bCtrl) { 522 if (IsMultipleSel()) { 523 if (nItemIndex >= 0 && nItemIndex < GetCount()) { 524 if (bCtrl) { 525 } else if (bShift) { 526 m_aSelItems.DeselectAll(); 527 m_aSelItems.Add(m_nFootIndex, nItemIndex); 528 SelectItems(); 529 } else { 530 m_aSelItems.DeselectAll(); 531 m_aSelItems.Add(nItemIndex); 532 SelectItems(); 533 m_nFootIndex = nItemIndex; 534 } 535 536 SetCaret(nItemIndex); 537 } 538 } else { 539 SetSingleSelect(nItemIndex); 540 } 541 542 if (!IsItemVisible(nItemIndex)) 543 ScrollToListItem(nItemIndex); 544 } 545 546 void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift, FX_BOOL bCtrl) { 547 OnVK(IsMultipleSel() ? GetCaret() - 1 : GetSelect() - 1, bShift, bCtrl); 548 } 549 550 void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift, FX_BOOL bCtrl) { 551 OnVK(IsMultipleSel() ? GetCaret() + 1 : GetSelect() + 1, bShift, bCtrl); 552 } 553 554 void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift, FX_BOOL bCtrl) { 555 OnVK(0, bShift, bCtrl); 556 } 557 558 void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift, FX_BOOL bCtrl) { 559 OnVK(GetCount() - 1, bShift, bCtrl); 560 } 561 562 void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift, FX_BOOL bCtrl) { 563 OnVK(0, bShift, bCtrl); 564 } 565 566 void CFX_ListCtrl::OnVK_END(FX_BOOL bShift, FX_BOOL bCtrl) { 567 OnVK(GetCount() - 1, bShift, bCtrl); 568 } 569 570 FX_BOOL CFX_ListCtrl::OnChar(FX_WORD nChar, FX_BOOL bShift, FX_BOOL bCtrl) { 571 int32_t nIndex = GetLastSelected(); 572 int32_t nFindIndex = FindNext(nIndex, nChar); 573 574 if (nFindIndex != nIndex) { 575 OnVK(nFindIndex, bShift, bCtrl); 576 return TRUE; 577 } 578 return FALSE; 579 } 580 581 void CFX_ListCtrl::SetPlateRect(const CPDF_Rect& rect) { 582 CFX_ListContainer::SetPlateRect(rect); 583 m_ptScrollPos.x = rect.left; 584 SetScrollPos(CPDF_Point(rect.left, rect.top)); 585 ReArrange(0); 586 InvalidateItem(-1); 587 } 588 589 CPDF_Rect CFX_ListCtrl::GetItemRect(int32_t nIndex) const { 590 return InToOut(CFX_List::GetItemRect(nIndex)); 591 } 592 593 void CFX_ListCtrl::AddString(const FX_WCHAR* string) { 594 AddItem(string); 595 ReArrange(GetCount() - 1); 596 } 597 598 void CFX_ListCtrl::SetMultipleSelect(int32_t nItemIndex, FX_BOOL bSelected) { 599 if (!IsValid(nItemIndex)) 600 return; 601 602 if (bSelected != IsItemSelected(nItemIndex)) { 603 if (bSelected) { 604 SetItemSelect(nItemIndex, TRUE); 605 InvalidateItem(nItemIndex); 606 } else { 607 SetItemSelect(nItemIndex, FALSE); 608 InvalidateItem(nItemIndex); 609 } 610 } 611 } 612 613 void CFX_ListCtrl::SetSingleSelect(int32_t nItemIndex) { 614 if (!IsValid(nItemIndex)) 615 return; 616 617 if (m_nSelItem != nItemIndex) { 618 if (m_nSelItem >= 0) { 619 SetItemSelect(m_nSelItem, FALSE); 620 InvalidateItem(m_nSelItem); 621 } 622 623 SetItemSelect(nItemIndex, TRUE); 624 InvalidateItem(nItemIndex); 625 m_nSelItem = nItemIndex; 626 } 627 } 628 629 void CFX_ListCtrl::SetCaret(int32_t nItemIndex) { 630 if (!IsValid(nItemIndex)) 631 return; 632 633 if (IsMultipleSel()) { 634 int32_t nOldIndex = m_nCaretIndex; 635 636 if (nOldIndex != nItemIndex) { 637 m_nCaretIndex = nItemIndex; 638 639 SetItemCaret(nOldIndex, FALSE); 640 SetItemCaret(nItemIndex, TRUE); 641 642 InvalidateItem(nOldIndex); 643 InvalidateItem(nItemIndex); 644 } 645 } 646 } 647 648 void CFX_ListCtrl::InvalidateItem(int32_t nItemIndex) { 649 if (m_pNotify) { 650 if (nItemIndex == -1) { 651 if (!m_bNotifyFlag) { 652 m_bNotifyFlag = TRUE; 653 CPDF_Rect rcRefresh = GetPlateRect(); 654 m_pNotify->IOnInvalidateRect(&rcRefresh); 655 m_bNotifyFlag = FALSE; 656 } 657 } else { 658 if (!m_bNotifyFlag) { 659 m_bNotifyFlag = TRUE; 660 CPDF_Rect rcRefresh = GetItemRect(nItemIndex); 661 rcRefresh.left -= 1.0f; 662 rcRefresh.right += 1.0f; 663 rcRefresh.bottom -= 1.0f; 664 rcRefresh.top += 1.0f; 665 666 m_pNotify->IOnInvalidateRect(&rcRefresh); 667 m_bNotifyFlag = FALSE; 668 } 669 } 670 } 671 } 672 673 void CFX_ListCtrl::SelectItems() { 674 for (int32_t i = 0, sz = m_aSelItems.GetCount(); i < sz; i++) { 675 int32_t nItemIndex = m_aSelItems.GetItemIndex(i); 676 int32_t nState = m_aSelItems.GetState(i); 677 678 switch (nState) { 679 case 1: 680 SetMultipleSelect(nItemIndex, TRUE); 681 break; 682 case -1: 683 SetMultipleSelect(nItemIndex, FALSE); 684 break; 685 } 686 } 687 688 m_aSelItems.Done(); 689 } 690 691 void CFX_ListCtrl::Select(int32_t nItemIndex) { 692 if (!IsValid(nItemIndex)) 693 return; 694 695 if (IsMultipleSel()) { 696 m_aSelItems.Add(nItemIndex); 697 SelectItems(); 698 } else { 699 SetSingleSelect(nItemIndex); 700 } 701 } 702 703 FX_BOOL CFX_ListCtrl::IsItemVisible(int32_t nItemIndex) const { 704 CPDF_Rect rcPlate = GetPlateRect(); 705 CPDF_Rect rcItem = GetItemRect(nItemIndex); 706 707 return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top; 708 } 709 710 void CFX_ListCtrl::ScrollToListItem(int32_t nItemIndex) { 711 if (!IsValid(nItemIndex)) 712 return; 713 714 CPDF_Rect rcPlate = GetPlateRect(); 715 CPDF_Rect rcItem = CFX_List::GetItemRect(nItemIndex); 716 CPDF_Rect rcItemCtrl = GetItemRect(nItemIndex); 717 718 if (FX_EDIT_IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) { 719 if (FX_EDIT_IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) { 720 SetScrollPosY(rcItem.bottom + rcPlate.Height()); 721 } 722 } else if (FX_EDIT_IsFloatBigger(rcItemCtrl.top, rcPlate.top)) { 723 if (FX_EDIT_IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) { 724 SetScrollPosY(rcItem.top); 725 } 726 } 727 } 728 729 void CFX_ListCtrl::SetScrollInfo() { 730 if (m_pNotify) { 731 CPDF_Rect rcPlate = GetPlateRect(); 732 CPDF_Rect rcContent = CFX_List::GetContentRect(); 733 734 if (!m_bNotifyFlag) { 735 m_bNotifyFlag = TRUE; 736 m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, 737 rcContent.bottom, rcContent.top, 738 GetFirstHeight(), rcPlate.Height()); 739 m_bNotifyFlag = FALSE; 740 } 741 } 742 } 743 744 void CFX_ListCtrl::SetScrollPos(const CPDF_Point& point) { 745 SetScrollPosY(point.y); 746 } 747 748 void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy) { 749 if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y, fy)) { 750 CPDF_Rect rcPlate = GetPlateRect(); 751 CPDF_Rect rcContent = CFX_List::GetContentRect(); 752 753 if (rcPlate.Height() > rcContent.Height()) { 754 fy = rcPlate.top; 755 } else { 756 if (FX_EDIT_IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) { 757 fy = rcContent.bottom + rcPlate.Height(); 758 } else if (FX_EDIT_IsFloatBigger(fy, rcContent.top)) { 759 fy = rcContent.top; 760 } 761 } 762 763 m_ptScrollPos.y = fy; 764 InvalidateItem(-1); 765 766 if (m_pNotify) { 767 if (!m_bNotifyFlag) { 768 m_bNotifyFlag = TRUE; 769 m_pNotify->IOnSetScrollPosY(fy); 770 m_bNotifyFlag = FALSE; 771 } 772 } 773 } 774 } 775 776 CPDF_Rect CFX_ListCtrl::GetContentRect() const { 777 return InToOut(CFX_List::GetContentRect()); 778 } 779 780 void CFX_ListCtrl::ReArrange(int32_t nItemIndex) { 781 CFX_List::ReArrange(nItemIndex); 782 SetScrollInfo(); 783 } 784 785 void CFX_ListCtrl::SetTopItem(int32_t nIndex) { 786 if (IsValid(nIndex)) { 787 GetPlateRect(); 788 CPDF_Rect rcItem = CFX_List::GetItemRect(nIndex); 789 SetScrollPosY(rcItem.top); 790 } 791 } 792 793 int32_t CFX_ListCtrl::GetTopItem() const { 794 int32_t nItemIndex = GetItemIndex(GetBTPoint()); 795 796 if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1)) 797 nItemIndex += 1; 798 799 return nItemIndex; 800 } 801 802 void CFX_ListCtrl::Empty() { 803 CFX_List::Empty(); 804 InvalidateItem(-1); 805 } 806 807 void CFX_ListCtrl::Cancel() { 808 m_aSelItems.DeselectAll(); 809 } 810 811 int32_t CFX_ListCtrl::GetItemIndex(const CPDF_Point& point) const { 812 return CFX_List::GetItemIndex(OutToIn(point)); 813 } 814 815 CFX_WideString CFX_ListCtrl::GetText() const { 816 if (IsMultipleSel()) 817 return GetItemText(m_nCaretIndex); 818 return GetItemText(m_nSelItem); 819 } 820