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 |