fxet_list.cpp revision ee451cb395940862dad63c85adfe8f2fd55e864c
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 13CFX_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 25CFX_ListItem::~CFX_ListItem() 26{ 27 IFX_Edit::DelEdit(m_pEdit); 28} 29 30void CFX_ListItem::SetFontMap(IFX_Edit_FontMap * pFontMap) 31{ 32 if (m_pEdit) 33 m_pEdit->SetFontMap(pFontMap); 34} 35 36IFX_Edit* CFX_ListItem::GetEdit() const 37{ 38 return m_pEdit; 39} 40 41IFX_Edit_Iterator* CFX_ListItem::GetIterator() const 42{ 43 if (m_pEdit) 44 return m_pEdit->GetIterator(); 45 46 return NULL; 47} 48 49void CFX_ListItem::SetRect(const CLST_Rect & rect) 50{ 51 m_rcListItem = rect; 52} 53 54CLST_Rect CFX_ListItem::GetRect() const 55{ 56 return m_rcListItem; 57} 58 59FX_BOOL CFX_ListItem::IsSelected() const 60{ 61 return m_bSelected; 62} 63 64void CFX_ListItem::SetSelect(FX_BOOL bSelected) 65{ 66 m_bSelected = bSelected; 67} 68 69FX_BOOL CFX_ListItem::IsCaret() const 70{ 71 return m_bCaret; 72} 73 74void CFX_ListItem::SetCaret(FX_BOOL bCaret) 75{ 76 m_bCaret = bCaret; 77} 78 79void CFX_ListItem::SetText(FX_LPCWSTR text) 80{ 81 if (m_pEdit) 82 m_pEdit->SetText(text); 83} 84 85void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) 86{ 87 if (m_pEdit) 88 m_pEdit->SetFontSize(fFontSize); 89} 90 91FX_FLOAT CFX_ListItem::GetItemHeight() const 92{ 93 if (m_pEdit) 94 return m_pEdit->GetContentRect().Height(); 95 96 return 0.0f; 97} 98 99FX_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 112CFX_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 122CFX_List::CFX_List() : m_pFontMap(NULL), m_fFontSize(0.0f), m_bMultiple(FALSE) 123{ 124} 125 126CFX_List::~CFX_List() 127{ 128 Empty(); 129} 130 131void 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 139void CFX_List::SetFontMap(IFX_Edit_FontMap * pFontMap) 140{ 141 m_pFontMap = pFontMap; 142} 143 144void CFX_List::SetFontSize(FX_FLOAT fFontSize) 145{ 146 m_fFontSize = fFontSize; 147} 148 149void 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 160void 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 180IFX_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 190FX_INT32 CFX_List::GetCount() const 191{ 192 return m_aListItems.GetSize(); 193} 194 195CPDF_Rect CFX_List::GetPlateRect() const 196{ 197 return CFX_ListContainer::GetPlateRect(); 198} 199 200CPDF_Rect CFX_List::GetContentRect() const 201{ 202 return InnerToOuter(CFX_ListContainer::GetContentRect()); 203} 204 205FX_FLOAT CFX_List::GetFontSize() const 206{ 207 return m_fFontSize; 208} 209 210FX_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 246FX_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 256FX_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 269FX_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 282FX_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 289FX_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 308CPDF_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 321FX_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 331void 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 339void 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 347void CFX_List::SetMultipleSel(FX_BOOL bMultiple) 348{ 349 m_bMultiple = bMultiple; 350} 351 352FX_BOOL CFX_List::IsMultipleSel() const 353{ 354 return m_bMultiple; 355} 356 357FX_BOOL CFX_List::IsValid(FX_INT32 nItemIndex) const 358{ 359 return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize(); 360} 361 362CFX_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 374CPLST_Select::CPLST_Select() 375{ 376} 377 378CPLST_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 386void 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 401void 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 413void 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 423void 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 435FX_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 449FX_BOOL CPLST_Select::IsExist(FX_INT32 nItemIndex) const 450{ 451 return Find(nItemIndex) >= 0; 452} 453 454FX_INT32 CPLST_Select::GetCount() const 455{ 456 return m_aItems.GetSize(); 457} 458 459FX_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 468FX_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 477void 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 488void 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 509CFX_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 519CFX_ListCtrl::~CFX_ListCtrl() 520{ 521} 522 523void CFX_ListCtrl::SetNotify(IFX_List_Notify * pNotify) 524{ 525 m_pNotify = pNotify; 526} 527 528CPDF_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 536CPDF_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 544CPDF_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 552CPDF_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 560void 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 609void 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 642void 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 677void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl) 678{ 679 OnVK(IsMultipleSel() ? GetCaret()-1 : GetSelect()-1, bShift, bCtrl); 680} 681 682void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl) 683{ 684 OnVK(IsMultipleSel() ? GetCaret()+1 : GetSelect()+1, bShift, bCtrl); 685} 686 687void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl) 688{ 689 OnVK(0, bShift, bCtrl); 690} 691 692void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl) 693{ 694 OnVK(GetCount()-1, bShift, bCtrl); 695} 696 697void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl) 698{ 699 OnVK(0, bShift, bCtrl); 700} 701 702void CFX_ListCtrl::OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl) 703{ 704 OnVK(GetCount()-1, bShift, bCtrl); 705} 706 707FX_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 722void 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 731CPDF_Rect CFX_ListCtrl::GetItemRect(FX_INT32 nIndex) const 732{ 733 return InToOut(CFX_List::GetItemRect(nIndex)); 734} 735 736void CFX_ListCtrl::AddString(FX_LPCWSTR string) 737{ 738 AddItem(string); 739 ReArrange(GetCount() - 1); 740} 741 742void 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 761void 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 779void 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 800void 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 832void 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 853void 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 866FX_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 874void 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 898void 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 915void CFX_ListCtrl::SetScrollPos(const CPDF_Point & point) 916{ 917 SetScrollPosY(point.y); 918} 919 920void 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 958CPDF_Rect CFX_ListCtrl::GetContentRect() const 959{ 960 return InToOut(CFX_List::GetContentRect()); 961} 962 963void CFX_ListCtrl::ReArrange(FX_INT32 nItemIndex) 964{ 965 CFX_List::ReArrange(nItemIndex); 966 SetScrollInfo(); 967} 968 969void 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 979FX_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 989void CFX_ListCtrl::Empty() 990{ 991 CFX_List::Empty(); 992 InvalidateItem(-1); 993} 994 995void CFX_ListCtrl::Cancel() 996{ 997 m_aSelItems.DeselectAll(); 998} 999 1000FX_INT32 CFX_ListCtrl::GetItemIndex(const CPDF_Point & point) const 1001{ 1002 return CFX_List::GetItemIndex(OutToIn(point)); 1003} 1004 1005CFX_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