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
CFX_ListItem()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
~CFX_ListItem()25 CFX_ListItem::~CFX_ListItem()
26 {
27 IFX_Edit::DelEdit(m_pEdit);
28 }
29
SetFontMap(IFX_Edit_FontMap * pFontMap)30 void CFX_ListItem::SetFontMap(IFX_Edit_FontMap * pFontMap)
31 {
32 if (m_pEdit)
33 m_pEdit->SetFontMap(pFontMap);
34 }
35
GetEdit() const36 IFX_Edit* CFX_ListItem::GetEdit() const
37 {
38 return m_pEdit;
39 }
40
GetIterator() const41 IFX_Edit_Iterator* CFX_ListItem::GetIterator() const
42 {
43 if (m_pEdit)
44 return m_pEdit->GetIterator();
45
46 return NULL;
47 }
48
SetRect(const CLST_Rect & rect)49 void CFX_ListItem::SetRect(const CLST_Rect & rect)
50 {
51 m_rcListItem = rect;
52 }
53
GetRect() const54 CLST_Rect CFX_ListItem::GetRect() const
55 {
56 return m_rcListItem;
57 }
58
IsSelected() const59 FX_BOOL CFX_ListItem::IsSelected() const
60 {
61 return m_bSelected;
62 }
63
SetSelect(FX_BOOL bSelected)64 void CFX_ListItem::SetSelect(FX_BOOL bSelected)
65 {
66 m_bSelected = bSelected;
67 }
68
IsCaret() const69 FX_BOOL CFX_ListItem::IsCaret() const
70 {
71 return m_bCaret;
72 }
73
SetCaret(FX_BOOL bCaret)74 void CFX_ListItem::SetCaret(FX_BOOL bCaret)
75 {
76 m_bCaret = bCaret;
77 }
78
SetText(FX_LPCWSTR text)79 void CFX_ListItem::SetText(FX_LPCWSTR text)
80 {
81 if (m_pEdit)
82 m_pEdit->SetText(text);
83 }
84
SetFontSize(FX_FLOAT fFontSize)85 void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize)
86 {
87 if (m_pEdit)
88 m_pEdit->SetFontSize(fFontSize);
89 }
90
GetItemHeight() const91 FX_FLOAT CFX_ListItem::GetItemHeight() const
92 {
93 if (m_pEdit)
94 return m_pEdit->GetContentRect().Height();
95
96 return 0.0f;
97 }
98
GetFirstChar() const99 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
GetText() const112 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
CFX_List()122 CFX_List::CFX_List() : m_fFontSize(0.0f), m_pFontMap(NULL), m_bMultiple(FALSE)
123 {
124 }
125
~CFX_List()126 CFX_List::~CFX_List()
127 {
128 Empty();
129 }
130
Empty()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
SetFontMap(IFX_Edit_FontMap * pFontMap)139 void CFX_List::SetFontMap(IFX_Edit_FontMap * pFontMap)
140 {
141 m_pFontMap = pFontMap;
142 }
143
SetFontSize(FX_FLOAT fFontSize)144 void CFX_List::SetFontSize(FX_FLOAT fFontSize)
145 {
146 m_fFontSize = fFontSize;
147 }
148
AddItem(FX_LPCWSTR str)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
ReArrange(FX_INT32 nItemIndex)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
GetItemEdit(FX_INT32 nIndex) const180 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
GetCount() const190 FX_INT32 CFX_List::GetCount() const
191 {
192 return m_aListItems.GetSize();
193 }
194
GetPlateRect() const195 CPDF_Rect CFX_List::GetPlateRect() const
196 {
197 return CFX_ListContainer::GetPlateRect();
198 }
199
GetContentRect() const200 CPDF_Rect CFX_List::GetContentRect() const
201 {
202 return InnerToOuter(CFX_ListContainer::GetContentRect());
203 }
204
GetFontSize() const205 FX_FLOAT CFX_List::GetFontSize() const
206 {
207 return m_fFontSize;
208 }
209
GetItemIndex(const CPDF_Point & point) const210 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
GetFirstHeight() const246 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
GetFirstSelected() const256 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
GetLastSelected() const269 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
Toupper(FX_WCHAR c) const282 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
FindNext(FX_INT32 nIndex,FX_WCHAR nChar) const289 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
GetItemRect(FX_INT32 nIndex) const308 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
IsItemSelected(FX_INT32 nIndex) const321 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
SetItemSelect(FX_INT32 nItemIndex,FX_BOOL bSelected)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
SetItemCaret(FX_INT32 nItemIndex,FX_BOOL bCaret)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
SetMultipleSel(FX_BOOL bMultiple)347 void CFX_List::SetMultipleSel(FX_BOOL bMultiple)
348 {
349 m_bMultiple = bMultiple;
350 }
351
IsMultipleSel() const352 FX_BOOL CFX_List::IsMultipleSel() const
353 {
354 return m_bMultiple;
355 }
356
IsValid(FX_INT32 nItemIndex) const357 FX_BOOL CFX_List::IsValid(FX_INT32 nItemIndex) const
358 {
359 return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize();
360 }
361
GetItemText(FX_INT32 nIndex) const362 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
CPLST_Select()374 CPLST_Select::CPLST_Select()
375 {
376 }
377
~CPLST_Select()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
Add(FX_INT32 nItemIndex)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
Add(FX_INT32 nBeginIndex,FX_INT32 nEndIndex)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
Sub(FX_INT32 nItemIndex)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
Sub(FX_INT32 nBeginIndex,FX_INT32 nEndIndex)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
Find(FX_INT32 nItemIndex) const435 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
IsExist(FX_INT32 nItemIndex) const449 FX_BOOL CPLST_Select::IsExist(FX_INT32 nItemIndex) const
450 {
451 return Find(nItemIndex) >= 0;
452 }
453
GetCount() const454 FX_INT32 CPLST_Select::GetCount() const
455 {
456 return m_aItems.GetSize();
457 }
458
GetItemIndex(FX_INT32 nIndex) const459 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
GetState(FX_INT32 nIndex) const468 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
DeselectAll()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
Done()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
CFX_ListCtrl()509 CFX_ListCtrl::CFX_ListCtrl() : m_pNotify(NULL),
510 m_bNotifyFlag(FALSE),
511 m_ptScrollPos(0.0f,0.0f),
512 m_nSelItem(-1),
513 m_nFootIndex(-1),
514 m_bCtrlSel(FALSE),
515 m_nCaretIndex(-1)
516 {
517 }
518
~CFX_ListCtrl()519 CFX_ListCtrl::~CFX_ListCtrl()
520 {
521 }
522
SetNotify(IFX_List_Notify * pNotify)523 void CFX_ListCtrl::SetNotify(IFX_List_Notify * pNotify)
524 {
525 m_pNotify = pNotify;
526 }
527
InToOut(const CPDF_Point & point) const528 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
OutToIn(const CPDF_Point & point) const536 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
InToOut(const CPDF_Rect & rect) const544 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
OutToIn(const CPDF_Rect & rect) const552 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
OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)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
OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl)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
OnVK(FX_INT32 nItemIndex,FX_BOOL bShift,FX_BOOL bCtrl)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
OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl)677 void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl)
678 {
679 OnVK(IsMultipleSel() ? GetCaret()-1 : GetSelect()-1, bShift, bCtrl);
680 }
681
OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl)682 void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl)
683 {
684 OnVK(IsMultipleSel() ? GetCaret()+1 : GetSelect()+1, bShift, bCtrl);
685 }
686
OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl)687 void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl)
688 {
689 OnVK(0, bShift, bCtrl);
690 }
691
OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl)692 void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl)
693 {
694 OnVK(GetCount()-1, bShift, bCtrl);
695 }
696
OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl)697 void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl)
698 {
699 OnVK(0, bShift, bCtrl);
700 }
701
OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl)702 void CFX_ListCtrl::OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl)
703 {
704 OnVK(GetCount()-1, bShift, bCtrl);
705 }
706
OnChar(FX_WORD nChar,FX_BOOL bShift,FX_BOOL bCtrl)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
SetPlateRect(const CPDF_Rect & rect)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
GetItemRect(FX_INT32 nIndex) const731 CPDF_Rect CFX_ListCtrl::GetItemRect(FX_INT32 nIndex) const
732 {
733 return InToOut(CFX_List::GetItemRect(nIndex));
734 }
735
AddString(FX_LPCWSTR string)736 void CFX_ListCtrl::AddString(FX_LPCWSTR string)
737 {
738 AddItem(string);
739 ReArrange(GetCount() - 1);
740 }
741
SetMultipleSelect(FX_INT32 nItemIndex,FX_BOOL bSelected)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
SetSingleSelect(FX_INT32 nItemIndex)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
SetCaret(FX_INT32 nItemIndex)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
InvalidateItem(FX_INT32 nItemIndex)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
SelectItems()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
Select(FX_INT32 nItemIndex)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
IsItemVisible(FX_INT32 nItemIndex) const866 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
ScrollToListItem(FX_INT32 nItemIndex)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
SetScrollInfo()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
SetScrollPos(const CPDF_Point & point)915 void CFX_ListCtrl::SetScrollPos(const CPDF_Point & point)
916 {
917 SetScrollPosY(point.y);
918 }
919
SetScrollPosY(FX_FLOAT fy)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
GetContentRect() const958 CPDF_Rect CFX_ListCtrl::GetContentRect() const
959 {
960 return InToOut(CFX_List::GetContentRect());
961 }
962
ReArrange(FX_INT32 nItemIndex)963 void CFX_ListCtrl::ReArrange(FX_INT32 nItemIndex)
964 {
965 CFX_List::ReArrange(nItemIndex);
966 SetScrollInfo();
967 }
968
SetTopItem(FX_INT32 nIndex)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
GetTopItem() const979 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
Empty()989 void CFX_ListCtrl::Empty()
990 {
991 CFX_List::Empty();
992 InvalidateItem(-1);
993 }
994
Cancel()995 void CFX_ListCtrl::Cancel()
996 {
997 m_aSelItems.DeselectAll();
998 }
999
GetItemIndex(const CPDF_Point & point) const1000 FX_INT32 CFX_ListCtrl::GetItemIndex(const CPDF_Point & point) const
1001 {
1002 return CFX_List::GetItemIndex(OutToIn(point));
1003 }
1004
GetText() const1005 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