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