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