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