// Copyright 2014 PDFium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
#include "../../include/fxedit/fxet_stub.h" | |
#include "../../include/fxedit/fxet_edit.h" | |
#include "../../include/fxedit/fxet_list.h" | |
/* ------------------------------- CFX_ListItem ---------------------------------- */ | |
CFX_ListItem::CFX_ListItem() : m_pEdit(NULL), | |
m_bSelected(FALSE), | |
m_bCaret(FALSE), | |
m_rcListItem(0.0f,0.0f,0.0f,0.0f) | |
{ | |
m_pEdit = IFX_Edit::NewEdit(); | |
ASSERT(m_pEdit != NULL); | |
m_pEdit->SetAlignmentV(1); | |
m_pEdit->Initialize(); | |
} | |
CFX_ListItem::~CFX_ListItem() | |
{ | |
IFX_Edit::DelEdit(m_pEdit); | |
} | |
void CFX_ListItem::SetFontMap(IFX_Edit_FontMap * pFontMap) | |
{ | |
if (m_pEdit) | |
m_pEdit->SetFontMap(pFontMap); | |
} | |
IFX_Edit* CFX_ListItem::GetEdit() const | |
{ | |
return m_pEdit; | |
} | |
IFX_Edit_Iterator* CFX_ListItem::GetIterator() const | |
{ | |
if (m_pEdit) | |
return m_pEdit->GetIterator(); | |
return NULL; | |
} | |
void CFX_ListItem::SetRect(const CLST_Rect & rect) | |
{ | |
m_rcListItem = rect; | |
} | |
CLST_Rect CFX_ListItem::GetRect() const | |
{ | |
return m_rcListItem; | |
} | |
FX_BOOL CFX_ListItem::IsSelected() const | |
{ | |
return m_bSelected; | |
} | |
void CFX_ListItem::SetSelect(FX_BOOL bSelected) | |
{ | |
m_bSelected = bSelected; | |
} | |
FX_BOOL CFX_ListItem::IsCaret() const | |
{ | |
return m_bCaret; | |
} | |
void CFX_ListItem::SetCaret(FX_BOOL bCaret) | |
{ | |
m_bCaret = bCaret; | |
} | |
void CFX_ListItem::SetText(FX_LPCWSTR text) | |
{ | |
if (m_pEdit) | |
m_pEdit->SetText(text); | |
} | |
void CFX_ListItem::SetFontSize(FX_FLOAT fFontSize) | |
{ | |
if (m_pEdit) | |
m_pEdit->SetFontSize(fFontSize); | |
} | |
FX_FLOAT CFX_ListItem::GetItemHeight() const | |
{ | |
if (m_pEdit) | |
return m_pEdit->GetContentRect().Height(); | |
return 0.0f; | |
} | |
FX_WORD CFX_ListItem::GetFirstChar() const | |
{ | |
CPVT_Word word; | |
if (IFX_Edit_Iterator* pIterator = GetIterator()) | |
{ | |
pIterator->SetAt(1); | |
pIterator->GetWord(word); | |
} | |
return word.Word; | |
} | |
CFX_WideString CFX_ListItem::GetText() const | |
{ | |
if (m_pEdit) | |
return m_pEdit->GetText(); | |
return L""; | |
} | |
/* ------------------------------------ CFX_List --------------------------------- */ | |
CFX_List::CFX_List() : m_pFontMap(NULL), m_fFontSize(0.0f), m_bMultiple(FALSE) | |
{ | |
} | |
CFX_List::~CFX_List() | |
{ | |
Empty(); | |
} | |
void CFX_List::Empty() | |
{ | |
for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++) | |
delete m_aListItems.GetAt(i); | |
m_aListItems.RemoveAll(); | |
} | |
void CFX_List::SetFontMap(IFX_Edit_FontMap * pFontMap) | |
{ | |
m_pFontMap = pFontMap; | |
} | |
void CFX_List::SetFontSize(FX_FLOAT fFontSize) | |
{ | |
m_fFontSize = fFontSize; | |
} | |
void CFX_List::AddItem(FX_LPCWSTR str) | |
{ | |
if (CFX_ListItem * pListItem = new CFX_ListItem()) | |
{ | |
pListItem->SetFontMap(m_pFontMap); | |
pListItem->SetFontSize(m_fFontSize); | |
pListItem->SetText(str); | |
m_aListItems.Add(pListItem); | |
} | |
} | |
void CFX_List::ReArrange(FX_INT32 nItemIndex) | |
{ | |
FX_FLOAT fPosY = 0.0f; | |
if (CFX_ListItem * pPrevItem = m_aListItems.GetAt(nItemIndex - 1)) | |
fPosY = pPrevItem->GetRect().bottom; | |
for (FX_INT32 i=nItemIndex,sz=m_aListItems.GetSize(); i<sz; i++) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(i)) | |
{ | |
FX_FLOAT fListItemHeight = pListItem->GetItemHeight(); | |
pListItem->SetRect(CLST_Rect(0.0f,fPosY,0.0f,fPosY + fListItemHeight)); | |
fPosY += fListItemHeight; | |
} | |
} | |
SetContentRect(CLST_Rect(0.0f,0.0f,0.0f,fPosY)); | |
} | |
IFX_Edit * CFX_List::GetItemEdit(FX_INT32 nIndex) const | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex)) | |
{ | |
return pListItem->GetEdit(); | |
} | |
return NULL; | |
} | |
FX_INT32 CFX_List::GetCount() const | |
{ | |
return m_aListItems.GetSize(); | |
} | |
CPDF_Rect CFX_List::GetPlateRect() const | |
{ | |
return CFX_ListContainer::GetPlateRect(); | |
} | |
CPDF_Rect CFX_List::GetContentRect() const | |
{ | |
return InnerToOuter(CFX_ListContainer::GetContentRect()); | |
} | |
FX_FLOAT CFX_List::GetFontSize() const | |
{ | |
return m_fFontSize; | |
} | |
FX_INT32 CFX_List::GetItemIndex(const CPDF_Point & point) const | |
{ | |
CPDF_Point pt = OuterToInner(point); | |
FX_BOOL bFirst = TRUE; | |
FX_BOOL bLast = TRUE; | |
for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(i)) | |
{ | |
CLST_Rect rcListItem = pListItem->GetRect(); | |
if (FX_EDIT_IsFloatBigger(pt.y, rcListItem.top)) | |
{ | |
bFirst = FALSE; | |
} | |
if (FX_EDIT_IsFloatSmaller(pt.y, rcListItem.bottom)) | |
{ | |
bLast = FALSE; | |
} | |
if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) | |
{ | |
return i; | |
} | |
} | |
} | |
if (bFirst) return 0; | |
if (bLast) return m_aListItems.GetSize()-1; | |
return -1; | |
} | |
FX_FLOAT CFX_List::GetFirstHeight() const | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(0)) | |
{ | |
return pListItem->GetItemHeight(); | |
} | |
return 1.0f; | |
} | |
FX_INT32 CFX_List::GetFirstSelected() const | |
{ | |
for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(i)) | |
{ | |
if (pListItem->IsSelected()) | |
return i; | |
} | |
} | |
return -1; | |
} | |
FX_INT32 CFX_List::GetLastSelected() const | |
{ | |
for (FX_INT32 i=m_aListItems.GetSize()-1; i>=0; i--) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(i)) | |
{ | |
if (pListItem->IsSelected()) | |
return i; | |
} | |
} | |
return -1; | |
} | |
FX_WCHAR CFX_List::Toupper(FX_WCHAR c) const | |
{ | |
if ( (c >= 'a') && (c <= 'z') ) | |
c = c - ('a' - 'A'); | |
return c; | |
} | |
FX_INT32 CFX_List::FindNext(FX_INT32 nIndex,FX_WCHAR nChar) const | |
{ | |
FX_INT32 nCircleIndex = nIndex; | |
for (FX_INT32 i=0,sz=m_aListItems.GetSize(); i<sz; i++) | |
{ | |
nCircleIndex ++; | |
if (nCircleIndex >= sz) nCircleIndex = 0; | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nCircleIndex)) | |
{ | |
if (Toupper(pListItem->GetFirstChar()) == Toupper(nChar)) | |
return nCircleIndex; | |
} | |
} | |
return nCircleIndex; | |
} | |
CPDF_Rect CFX_List::GetItemRect(FX_INT32 nIndex) const | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex)) | |
{ | |
CPDF_Rect rcItem = pListItem->GetRect(); | |
rcItem.left = 0.0f; | |
rcItem.right = GetPlateRect().Width(); | |
return InnerToOuter(rcItem); | |
} | |
return CPDF_Rect(); | |
} | |
FX_BOOL CFX_List::IsItemSelected(FX_INT32 nIndex) const | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex)) | |
{ | |
return pListItem->IsSelected(); | |
} | |
return FALSE; | |
} | |
void CFX_List::SetItemSelect(FX_INT32 nItemIndex, FX_BOOL bSelected) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nItemIndex)) | |
{ | |
pListItem->SetSelect(bSelected); | |
} | |
} | |
void CFX_List::SetItemCaret(FX_INT32 nItemIndex, FX_BOOL bCaret) | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nItemIndex)) | |
{ | |
pListItem->SetCaret(bCaret); | |
} | |
} | |
void CFX_List::SetMultipleSel(FX_BOOL bMultiple) | |
{ | |
m_bMultiple = bMultiple; | |
} | |
FX_BOOL CFX_List::IsMultipleSel() const | |
{ | |
return m_bMultiple; | |
} | |
FX_BOOL CFX_List::IsValid(FX_INT32 nItemIndex) const | |
{ | |
return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize(); | |
} | |
CFX_WideString CFX_List::GetItemText(FX_INT32 nIndex) const | |
{ | |
if (CFX_ListItem * pListItem = m_aListItems.GetAt(nIndex)) | |
{ | |
return pListItem->GetText(); | |
} | |
return L""; | |
} | |
/* ------------------------------------ CPLST_Select ---------------------------------- */ | |
CPLST_Select::CPLST_Select() | |
{ | |
} | |
CPLST_Select::~CPLST_Select() | |
{ | |
for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++) | |
delete m_aItems.GetAt(i); | |
m_aItems.RemoveAll(); | |
} | |
void CPLST_Select::Add(FX_INT32 nItemIndex) | |
{ | |
FX_INT32 nIndex = Find(nItemIndex); | |
if (nIndex < 0) | |
m_aItems.Add(new CPLST_Select_Item(nItemIndex,1)); | |
else | |
{ | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex)) | |
{ | |
pItem->nState = 1; | |
} | |
} | |
} | |
void CPLST_Select::Add(FX_INT32 nBeginIndex, FX_INT32 nEndIndex) | |
{ | |
if (nBeginIndex > nEndIndex) | |
{ | |
FX_INT32 nTemp = nEndIndex; | |
nEndIndex = nBeginIndex; | |
nBeginIndex = nTemp; | |
} | |
for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Add(i); | |
} | |
void CPLST_Select::Sub(FX_INT32 nItemIndex) | |
{ | |
for (FX_INT32 i=m_aItems.GetSize()-1; i>=0; i--) | |
{ | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(i)) | |
if (pItem->nItemIndex == nItemIndex) | |
pItem->nState = -1; | |
} | |
} | |
void CPLST_Select::Sub(FX_INT32 nBeginIndex, FX_INT32 nEndIndex) | |
{ | |
if (nBeginIndex > nEndIndex) | |
{ | |
FX_INT32 nTemp = nEndIndex; | |
nEndIndex = nBeginIndex; | |
nBeginIndex = nTemp; | |
} | |
for (FX_INT32 i=nBeginIndex; i<=nEndIndex; i++) Sub(i); | |
} | |
FX_INT32 CPLST_Select::Find(FX_INT32 nItemIndex) const | |
{ | |
for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++) | |
{ | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(i)) | |
{ | |
if (pItem->nItemIndex == nItemIndex) | |
return i; | |
} | |
} | |
return -1; | |
} | |
FX_BOOL CPLST_Select::IsExist(FX_INT32 nItemIndex) const | |
{ | |
return Find(nItemIndex) >= 0; | |
} | |
FX_INT32 CPLST_Select::GetCount() const | |
{ | |
return m_aItems.GetSize(); | |
} | |
FX_INT32 CPLST_Select::GetItemIndex(FX_INT32 nIndex) const | |
{ | |
if (nIndex >= 0 && nIndex < m_aItems.GetSize()) | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex)) | |
return pItem->nItemIndex; | |
return -1; | |
} | |
FX_INT32 CPLST_Select::GetState(FX_INT32 nIndex) const | |
{ | |
if (nIndex >= 0 && nIndex < m_aItems.GetSize()) | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(nIndex)) | |
return pItem->nState; | |
return 0; | |
} | |
void CPLST_Select::DeselectAll() | |
{ | |
for (FX_INT32 i=0,sz=m_aItems.GetSize(); i<sz; i++) | |
{ | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(i)) | |
{ | |
pItem->nState = -1; | |
} | |
} | |
} | |
void CPLST_Select::Done() | |
{ | |
for (FX_INT32 i=m_aItems.GetSize()-1; i>=0; i--) | |
{ | |
if (CPLST_Select_Item * pItem = m_aItems.GetAt(i)) | |
{ | |
if (pItem->nState == -1) | |
{ | |
delete pItem; | |
m_aItems.RemoveAt(i); | |
} | |
else | |
{ | |
pItem->nState = 0; | |
} | |
} | |
} | |
} | |
/* ------------------------------------ CFX_ListCtrl --------------------------------- */ | |
CFX_ListCtrl::CFX_ListCtrl() : m_pNotify(NULL), | |
m_ptScrollPos(0.0f,0.0f), | |
m_nSelItem(-1), | |
m_nFootIndex(-1), | |
m_bCtrlSel(FALSE), | |
m_nCaretIndex(-1), | |
m_bNotifyFlag(FALSE) | |
{ | |
} | |
CFX_ListCtrl::~CFX_ListCtrl() | |
{ | |
} | |
void CFX_ListCtrl::SetNotify(IFX_List_Notify * pNotify) | |
{ | |
m_pNotify = pNotify; | |
} | |
CPDF_Point CFX_ListCtrl::InToOut(const CPDF_Point & point) const | |
{ | |
CPDF_Rect rcPlate = GetPlateRect(); | |
return CPDF_Point(point.x - (m_ptScrollPos.x - rcPlate.left), | |
point.y - (m_ptScrollPos.y - rcPlate.top)); | |
} | |
CPDF_Point CFX_ListCtrl::OutToIn(const CPDF_Point & point) const | |
{ | |
CPDF_Rect rcPlate = GetPlateRect(); | |
return CPDF_Point(point.x + (m_ptScrollPos.x - rcPlate.left), | |
point.y + (m_ptScrollPos.y - rcPlate.top)); | |
} | |
CPDF_Rect CFX_ListCtrl::InToOut(const CPDF_Rect & rect) const | |
{ | |
CPDF_Point ptLeftBottom = InToOut(CPDF_Point(rect.left,rect.bottom)); | |
CPDF_Point ptRightTop = InToOut(CPDF_Point(rect.right,rect.top)); | |
return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y); | |
} | |
CPDF_Rect CFX_ListCtrl::OutToIn(const CPDF_Rect & rect) const | |
{ | |
CPDF_Point ptLeftBottom = OutToIn(CPDF_Point(rect.left,rect.bottom)); | |
CPDF_Point ptRightTop = OutToIn(CPDF_Point(rect.right,rect.top)); | |
return CPDF_Rect(ptLeftBottom.x,ptLeftBottom.y,ptRightTop.x,ptRightTop.y); | |
} | |
void CFX_ListCtrl::OnMouseDown(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
FX_INT32 nHitIndex = this->GetItemIndex(point); | |
if (IsMultipleSel()) | |
{ | |
if (bCtrl) | |
{ | |
if (IsItemSelected(nHitIndex)) | |
{ | |
m_aSelItems.Sub(nHitIndex); | |
SelectItems(); | |
m_bCtrlSel = FALSE; | |
} | |
else | |
{ | |
m_aSelItems.Add(nHitIndex); | |
SelectItems(); | |
m_bCtrlSel = TRUE; | |
} | |
m_nFootIndex = nHitIndex; | |
} | |
else if (bShift) | |
{ | |
m_aSelItems.DeselectAll(); | |
m_aSelItems.Add(m_nFootIndex,nHitIndex); | |
SelectItems(); | |
} | |
else | |
{ | |
m_aSelItems.DeselectAll(); | |
m_aSelItems.Add(nHitIndex); | |
SelectItems(); | |
m_nFootIndex = nHitIndex; | |
} | |
SetCaret(nHitIndex); | |
} | |
else | |
{ | |
SetSingleSelect(nHitIndex); | |
} | |
if (!this->IsItemVisible(nHitIndex)) | |
this->ScrollToListItem(nHitIndex); | |
} | |
void CFX_ListCtrl::OnMouseMove(const CPDF_Point & point,FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
FX_INT32 nHitIndex = this->GetItemIndex(point); | |
if (IsMultipleSel()) | |
{ | |
if (bCtrl) | |
{ | |
if (m_bCtrlSel) | |
m_aSelItems.Add(m_nFootIndex,nHitIndex); | |
else | |
m_aSelItems.Sub(m_nFootIndex,nHitIndex); | |
SelectItems(); | |
} | |
else | |
{ | |
m_aSelItems.DeselectAll(); | |
m_aSelItems.Add(m_nFootIndex,nHitIndex); | |
SelectItems(); | |
} | |
SetCaret(nHitIndex); | |
} | |
else | |
{ | |
SetSingleSelect(nHitIndex); | |
} | |
if (!this->IsItemVisible(nHitIndex)) | |
this->ScrollToListItem(nHitIndex); | |
} | |
void CFX_ListCtrl::OnVK(FX_INT32 nItemIndex,FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
if (IsMultipleSel()) | |
{ | |
if (nItemIndex >= 0 && nItemIndex < GetCount()) | |
{ | |
if (bCtrl) | |
{ | |
} | |
else if (bShift) | |
{ | |
m_aSelItems.DeselectAll(); | |
m_aSelItems.Add(m_nFootIndex,nItemIndex); | |
SelectItems(); | |
} | |
else | |
{ | |
m_aSelItems.DeselectAll(); | |
m_aSelItems.Add(nItemIndex); | |
SelectItems(); | |
m_nFootIndex = nItemIndex; | |
} | |
SetCaret(nItemIndex); | |
} | |
} | |
else | |
{ | |
SetSingleSelect(nItemIndex); | |
} | |
if (!this->IsItemVisible(nItemIndex)) | |
this->ScrollToListItem(nItemIndex); | |
} | |
void CFX_ListCtrl::OnVK_UP(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(IsMultipleSel() ? GetCaret()-1 : GetSelect()-1, bShift, bCtrl); | |
} | |
void CFX_ListCtrl::OnVK_DOWN(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(IsMultipleSel() ? GetCaret()+1 : GetSelect()+1, bShift, bCtrl); | |
} | |
void CFX_ListCtrl::OnVK_LEFT(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(0, bShift, bCtrl); | |
} | |
void CFX_ListCtrl::OnVK_RIGHT(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(GetCount()-1, bShift, bCtrl); | |
} | |
void CFX_ListCtrl::OnVK_HOME(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(0, bShift, bCtrl); | |
} | |
void CFX_ListCtrl::OnVK_END(FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
OnVK(GetCount()-1, bShift, bCtrl); | |
} | |
FX_BOOL CFX_ListCtrl::OnChar(FX_WORD nChar,FX_BOOL bShift,FX_BOOL bCtrl) | |
{ | |
FX_INT32 nIndex = GetLastSelected(); | |
FX_INT32 nFindIndex = FindNext(nIndex,nChar); | |
if (nFindIndex != nIndex) | |
{ | |
OnVK(nFindIndex, bShift, bCtrl); | |
return TRUE; | |
} | |
return FALSE; | |
} | |
/* -------- inner methods ------- */ | |
void CFX_ListCtrl::SetPlateRect(const CPDF_Rect & rect) | |
{ | |
CFX_ListContainer::SetPlateRect(rect); | |
m_ptScrollPos.x = rect.left; | |
SetScrollPos(CPDF_Point(rect.left,rect.top)); | |
ReArrange(0); | |
InvalidateItem(-1); | |
} | |
CPDF_Rect CFX_ListCtrl::GetItemRect(FX_INT32 nIndex) const | |
{ | |
return InToOut(CFX_List::GetItemRect(nIndex)); | |
} | |
void CFX_ListCtrl::AddString(FX_LPCWSTR string) | |
{ | |
AddItem(string); | |
ReArrange(GetCount() - 1); | |
} | |
void CFX_ListCtrl::SetMultipleSelect(FX_INT32 nItemIndex, FX_BOOL bSelected) | |
{ | |
if (!IsValid(nItemIndex)) return; | |
if (bSelected != this->IsItemSelected(nItemIndex)) | |
{ | |
if (bSelected) | |
{ | |
SetItemSelect(nItemIndex,TRUE); | |
InvalidateItem(nItemIndex); | |
} | |
else | |
{ | |
SetItemSelect(nItemIndex,FALSE); | |
InvalidateItem(nItemIndex); | |
} | |
} | |
} | |
void CFX_ListCtrl::SetSingleSelect(FX_INT32 nItemIndex) | |
{ | |
if (!IsValid(nItemIndex)) return; | |
if (m_nSelItem != nItemIndex) | |
{ | |
if (m_nSelItem >= 0) | |
{ | |
SetItemSelect(m_nSelItem,FALSE); | |
InvalidateItem(m_nSelItem); | |
} | |
SetItemSelect(nItemIndex,TRUE); | |
InvalidateItem(nItemIndex); | |
m_nSelItem = nItemIndex; | |
} | |
} | |
void CFX_ListCtrl::SetCaret(FX_INT32 nItemIndex) | |
{ | |
if (!IsValid(nItemIndex)) return; | |
if (this->IsMultipleSel()) | |
{ | |
FX_INT32 nOldIndex = m_nCaretIndex; | |
if (nOldIndex != nItemIndex) | |
{ | |
m_nCaretIndex = nItemIndex; | |
SetItemCaret(nOldIndex, FALSE); | |
SetItemCaret(nItemIndex,TRUE); | |
InvalidateItem(nOldIndex); | |
InvalidateItem(nItemIndex); | |
} | |
} | |
} | |
void CFX_ListCtrl::InvalidateItem(FX_INT32 nItemIndex) | |
{ | |
if (m_pNotify) | |
{ | |
if (nItemIndex == -1) | |
{ | |
if (!m_bNotifyFlag) | |
{ | |
m_bNotifyFlag = TRUE; | |
CPDF_Rect rcRefresh = GetPlateRect(); | |
m_pNotify->IOnInvalidateRect(&rcRefresh); | |
m_bNotifyFlag = FALSE; | |
} | |
} | |
else | |
{ | |
if (!m_bNotifyFlag) | |
{ | |
m_bNotifyFlag = TRUE; | |
CPDF_Rect rcRefresh = GetItemRect(nItemIndex); | |
rcRefresh.left -= 1.0f; | |
rcRefresh.right += 1.0f; | |
rcRefresh.bottom -= 1.0f; | |
rcRefresh.top += 1.0f; | |
m_pNotify->IOnInvalidateRect(&rcRefresh); | |
m_bNotifyFlag = FALSE; | |
} | |
} | |
} | |
} | |
void CFX_ListCtrl::SelectItems() | |
{ | |
for (FX_INT32 i=0,sz=m_aSelItems.GetCount(); i<sz; i++) | |
{ | |
FX_INT32 nItemIndex = m_aSelItems.GetItemIndex(i); | |
FX_INT32 nState = m_aSelItems.GetState(i); | |
switch(nState) | |
{ | |
case 1: | |
SetMultipleSelect(nItemIndex, TRUE); | |
break; | |
case -1: | |
SetMultipleSelect(nItemIndex, FALSE); | |
break; | |
} | |
} | |
m_aSelItems.Done(); | |
} | |
void CFX_ListCtrl::Select(FX_INT32 nItemIndex) | |
{ | |
if (!IsValid(nItemIndex)) return; | |
if (this->IsMultipleSel()) | |
{ | |
m_aSelItems.Add(nItemIndex); | |
SelectItems(); | |
} | |
else | |
SetSingleSelect(nItemIndex); | |
} | |
FX_BOOL CFX_ListCtrl::IsItemVisible(FX_INT32 nItemIndex) const | |
{ | |
CPDF_Rect rcPlate = this->GetPlateRect(); | |
CPDF_Rect rcItem = this->GetItemRect(nItemIndex); | |
return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top; | |
} | |
void CFX_ListCtrl::ScrollToListItem(FX_INT32 nItemIndex) | |
{ | |
if (!IsValid(nItemIndex)) return; | |
CPDF_Rect rcPlate = this->GetPlateRect(); | |
CPDF_Rect rcItem = CFX_List::GetItemRect(nItemIndex); | |
CPDF_Rect rcItemCtrl = GetItemRect(nItemIndex); | |
if (FX_EDIT_IsFloatSmaller(rcItemCtrl.bottom, rcPlate.bottom)) | |
{ | |
if (FX_EDIT_IsFloatSmaller(rcItemCtrl.top, rcPlate.top)) | |
{ | |
SetScrollPosY(rcItem.bottom + rcPlate.Height()); | |
} | |
} | |
else if (FX_EDIT_IsFloatBigger(rcItemCtrl.top, rcPlate.top)) | |
{ | |
if (FX_EDIT_IsFloatBigger(rcItemCtrl.bottom, rcPlate.bottom)) | |
{ | |
SetScrollPosY(rcItem.top); | |
} | |
} | |
} | |
void CFX_ListCtrl::SetScrollInfo() | |
{ | |
if (m_pNotify) | |
{ | |
CPDF_Rect rcPlate = GetPlateRect(); | |
CPDF_Rect rcContent = CFX_List::GetContentRect(); | |
if (!m_bNotifyFlag) | |
{ | |
m_bNotifyFlag = TRUE; | |
m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, | |
rcContent.bottom, rcContent.top, GetFirstHeight(), rcPlate.Height()); | |
m_bNotifyFlag = FALSE; | |
} | |
} | |
} | |
void CFX_ListCtrl::SetScrollPos(const CPDF_Point & point) | |
{ | |
SetScrollPosY(point.y); | |
} | |
void CFX_ListCtrl::SetScrollPosY(FX_FLOAT fy) | |
{ | |
if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.y,fy)) | |
{ | |
CPDF_Rect rcPlate = this->GetPlateRect(); | |
CPDF_Rect rcContent = CFX_List::GetContentRect(); | |
if (rcPlate.Height() > rcContent.Height()) | |
{ | |
fy = rcPlate.top; | |
} | |
else | |
{ | |
if (FX_EDIT_IsFloatSmaller(fy - rcPlate.Height(), rcContent.bottom)) | |
{ | |
fy = rcContent.bottom + rcPlate.Height(); | |
} | |
else if (FX_EDIT_IsFloatBigger(fy, rcContent.top)) | |
{ | |
fy = rcContent.top; | |
} | |
} | |
m_ptScrollPos.y = fy; | |
InvalidateItem(-1); | |
if (m_pNotify) | |
{ | |
if (!m_bNotifyFlag) | |
{ | |
m_bNotifyFlag = TRUE; | |
m_pNotify->IOnSetScrollPosY(fy); | |
m_bNotifyFlag = FALSE; | |
} | |
} | |
} | |
} | |
CPDF_Rect CFX_ListCtrl::GetContentRect() const | |
{ | |
return InToOut(CFX_List::GetContentRect()); | |
} | |
void CFX_ListCtrl::ReArrange(FX_INT32 nItemIndex) | |
{ | |
CFX_List::ReArrange(nItemIndex); | |
SetScrollInfo(); | |
} | |
void CFX_ListCtrl::SetTopItem(FX_INT32 nIndex) | |
{ | |
if (IsValid(nIndex)) | |
{ | |
this->GetPlateRect(); | |
CPDF_Rect rcItem = CFX_List::GetItemRect(nIndex); | |
SetScrollPosY(rcItem.top); | |
} | |
} | |
FX_INT32 CFX_ListCtrl::GetTopItem() const | |
{ | |
FX_INT32 nItemIndex = this->GetItemIndex(this->GetBTPoint()); | |
if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1)) | |
nItemIndex += 1; | |
return nItemIndex; | |
} | |
void CFX_ListCtrl::Empty() | |
{ | |
CFX_List::Empty(); | |
InvalidateItem(-1); | |
} | |
void CFX_ListCtrl::Cancel() | |
{ | |
m_aSelItems.DeselectAll(); | |
} | |
FX_INT32 CFX_ListCtrl::GetItemIndex(const CPDF_Point & point) const | |
{ | |
return CFX_List::GetItemIndex(OutToIn(point)); | |
} | |
CFX_WideString CFX_ListCtrl::GetText() const | |
{ | |
if (this->IsMultipleSel()) | |
return this->GetItemText(this->m_nCaretIndex); | |
else | |
return this->GetItemText(this->m_nSelItem); | |
} | |