| // 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(const FX_WCHAR* 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_fFontSize(0.0f), m_pFontMap(NULL), m_bMultiple(FALSE) {} | |
| CFX_List::~CFX_List() { | |
| Empty(); | |
| } | |
| void CFX_List::Empty() { | |
| for (int32_t 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(const FX_WCHAR* str) { | |
| 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(int32_t nItemIndex) { | |
| FX_FLOAT fPosY = 0.0f; | |
| if (CFX_ListItem* pPrevItem = m_aListItems.GetAt(nItemIndex - 1)) | |
| fPosY = pPrevItem->GetRect().bottom; | |
| for (int32_t 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(int32_t nIndex) const { | |
| if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { | |
| return pListItem->GetEdit(); | |
| } | |
| return NULL; | |
| } | |
| int32_t 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; | |
| } | |
| int32_t CFX_List::GetItemIndex(const CPDF_Point& point) const { | |
| CPDF_Point pt = OuterToInner(point); | |
| FX_BOOL bFirst = TRUE; | |
| FX_BOOL bLast = TRUE; | |
| for (int32_t 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; | |
| } | |
| int32_t CFX_List::GetFirstSelected() const { | |
| for (int32_t i = 0, sz = m_aListItems.GetSize(); i < sz; i++) { | |
| if (CFX_ListItem* pListItem = m_aListItems.GetAt(i)) { | |
| if (pListItem->IsSelected()) | |
| return i; | |
| } | |
| } | |
| return -1; | |
| } | |
| int32_t CFX_List::GetLastSelected() const { | |
| for (int32_t 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; | |
| } | |
| int32_t CFX_List::FindNext(int32_t nIndex, FX_WCHAR nChar) const { | |
| int32_t nCircleIndex = nIndex; | |
| for (int32_t 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(int32_t 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(int32_t nIndex) const { | |
| if (CFX_ListItem* pListItem = m_aListItems.GetAt(nIndex)) { | |
| return pListItem->IsSelected(); | |
| } | |
| return FALSE; | |
| } | |
| void CFX_List::SetItemSelect(int32_t nItemIndex, FX_BOOL bSelected) { | |
| if (CFX_ListItem* pListItem = m_aListItems.GetAt(nItemIndex)) { | |
| pListItem->SetSelect(bSelected); | |
| } | |
| } | |
| void CFX_List::SetItemCaret(int32_t 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(int32_t nItemIndex) const { | |
| return nItemIndex >= 0 && nItemIndex < m_aListItems.GetSize(); | |
| } | |
| CFX_WideString CFX_List::GetItemText(int32_t 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 (int32_t i = 0, sz = m_aItems.GetSize(); i < sz; i++) | |
| delete m_aItems.GetAt(i); | |
| m_aItems.RemoveAll(); | |
| } | |
| void CPLST_Select::Add(int32_t nItemIndex) { | |
| int32_t 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(int32_t nBeginIndex, int32_t nEndIndex) { | |
| if (nBeginIndex > nEndIndex) { | |
| int32_t nTemp = nEndIndex; | |
| nEndIndex = nBeginIndex; | |
| nBeginIndex = nTemp; | |
| } | |
| for (int32_t i = nBeginIndex; i <= nEndIndex; i++) | |
| Add(i); | |
| } | |
| void CPLST_Select::Sub(int32_t nItemIndex) { | |
| for (int32_t 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(int32_t nBeginIndex, int32_t nEndIndex) { | |
| if (nBeginIndex > nEndIndex) { | |
| int32_t nTemp = nEndIndex; | |
| nEndIndex = nBeginIndex; | |
| nBeginIndex = nTemp; | |
| } | |
| for (int32_t i = nBeginIndex; i <= nEndIndex; i++) | |
| Sub(i); | |
| } | |
| int32_t CPLST_Select::Find(int32_t nItemIndex) const { | |
| for (int32_t 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(int32_t nItemIndex) const { | |
| return Find(nItemIndex) >= 0; | |
| } | |
| int32_t CPLST_Select::GetCount() const { | |
| return m_aItems.GetSize(); | |
| } | |
| int32_t CPLST_Select::GetItemIndex(int32_t nIndex) const { | |
| if (nIndex >= 0 && nIndex < m_aItems.GetSize()) | |
| if (CPLST_Select_Item* pItem = m_aItems.GetAt(nIndex)) | |
| return pItem->nItemIndex; | |
| return -1; | |
| } | |
| int32_t CPLST_Select::GetState(int32_t 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 (int32_t 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 (int32_t 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_bNotifyFlag(FALSE), | |
| m_ptScrollPos(0.0f, 0.0f), | |
| m_nSelItem(-1), | |
| m_nFootIndex(-1), | |
| m_bCtrlSel(FALSE), | |
| m_nCaretIndex(-1) {} | |
| 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) { | |
| int32_t nHitIndex = 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 (!IsItemVisible(nHitIndex)) | |
| ScrollToListItem(nHitIndex); | |
| } | |
| void CFX_ListCtrl::OnMouseMove(const CPDF_Point& point, | |
| FX_BOOL bShift, | |
| FX_BOOL bCtrl) { | |
| int32_t nHitIndex = 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 (!IsItemVisible(nHitIndex)) | |
| ScrollToListItem(nHitIndex); | |
| } | |
| void CFX_ListCtrl::OnVK(int32_t 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 (!IsItemVisible(nItemIndex)) | |
| 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) { | |
| int32_t nIndex = GetLastSelected(); | |
| int32_t 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(int32_t nIndex) const { | |
| return InToOut(CFX_List::GetItemRect(nIndex)); | |
| } | |
| void CFX_ListCtrl::AddString(const FX_WCHAR* string) { | |
| AddItem(string); | |
| ReArrange(GetCount() - 1); | |
| } | |
| void CFX_ListCtrl::SetMultipleSelect(int32_t nItemIndex, FX_BOOL bSelected) { | |
| if (!IsValid(nItemIndex)) | |
| return; | |
| if (bSelected != IsItemSelected(nItemIndex)) { | |
| if (bSelected) { | |
| SetItemSelect(nItemIndex, TRUE); | |
| InvalidateItem(nItemIndex); | |
| } else { | |
| SetItemSelect(nItemIndex, FALSE); | |
| InvalidateItem(nItemIndex); | |
| } | |
| } | |
| } | |
| void CFX_ListCtrl::SetSingleSelect(int32_t 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(int32_t nItemIndex) { | |
| if (!IsValid(nItemIndex)) | |
| return; | |
| if (IsMultipleSel()) { | |
| int32_t nOldIndex = m_nCaretIndex; | |
| if (nOldIndex != nItemIndex) { | |
| m_nCaretIndex = nItemIndex; | |
| SetItemCaret(nOldIndex, FALSE); | |
| SetItemCaret(nItemIndex, TRUE); | |
| InvalidateItem(nOldIndex); | |
| InvalidateItem(nItemIndex); | |
| } | |
| } | |
| } | |
| void CFX_ListCtrl::InvalidateItem(int32_t 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 (int32_t i = 0, sz = m_aSelItems.GetCount(); i < sz; i++) { | |
| int32_t nItemIndex = m_aSelItems.GetItemIndex(i); | |
| int32_t 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(int32_t nItemIndex) { | |
| if (!IsValid(nItemIndex)) | |
| return; | |
| if (IsMultipleSel()) { | |
| m_aSelItems.Add(nItemIndex); | |
| SelectItems(); | |
| } else | |
| SetSingleSelect(nItemIndex); | |
| } | |
| FX_BOOL CFX_ListCtrl::IsItemVisible(int32_t nItemIndex) const { | |
| CPDF_Rect rcPlate = GetPlateRect(); | |
| CPDF_Rect rcItem = GetItemRect(nItemIndex); | |
| return rcItem.bottom >= rcPlate.bottom && rcItem.top <= rcPlate.top; | |
| } | |
| void CFX_ListCtrl::ScrollToListItem(int32_t nItemIndex) { | |
| if (!IsValid(nItemIndex)) | |
| return; | |
| CPDF_Rect rcPlate = 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 = 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(int32_t nItemIndex) { | |
| CFX_List::ReArrange(nItemIndex); | |
| SetScrollInfo(); | |
| } | |
| void CFX_ListCtrl::SetTopItem(int32_t nIndex) { | |
| if (IsValid(nIndex)) { | |
| GetPlateRect(); | |
| CPDF_Rect rcItem = CFX_List::GetItemRect(nIndex); | |
| SetScrollPosY(rcItem.top); | |
| } | |
| } | |
| int32_t CFX_ListCtrl::GetTopItem() const { | |
| int32_t nItemIndex = GetItemIndex(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(); | |
| } | |
| int32_t CFX_ListCtrl::GetItemIndex(const CPDF_Point& point) const { | |
| return CFX_List::GetItemIndex(OutToIn(point)); | |
| } | |
| CFX_WideString CFX_ListCtrl::GetText() const { | |
| if (IsMultipleSel()) | |
| return GetItemText(m_nCaretIndex); | |
| return GetItemText(m_nSelItem); | |
| } |