7#include "fpdfsdk/pwl/cpwl_list_ctrl.h"
12#include "core/fpdfdoc/cpvt_word.h"
13#include "core/fxcrt/fx_extension.h"
14#include "core/fxcrt/stl_util.h"
15#include "fpdfsdk/pwl/cpwl_edit_impl.h"
16#include "fpdfsdk/pwl/cpwl_list_box.h"
17#include "third_party/base/numerics/safe_conversions.h"
21CPWL_ListCtrl::Item::Item() : m_pEdit(std::make_unique<CPWL_EditImpl>()) {
22 m_pEdit->SetAlignmentV(1);
23 m_pEdit->Initialize();
29 m_pEdit->SetFontMap(pFontMap);
33 m_pEdit->SetText(text);
38 m_pEdit->SetFontSize(fFontSize);
43 return m_pEdit->GetContentRect().Height();
55 return m_pEdit->GetText();
63 m_Items[nItemIndex] = SELECTING;
66void CPWL_ListCtrl::SelectState::Add(int32_t nBeginIndex, int32_t nEndIndex) {
67 if (nBeginIndex > nEndIndex)
68 std::swap(nBeginIndex, nEndIndex);
70 for (int32_t i = nBeginIndex; i <= nEndIndex; ++i)
75 auto it = m_Items.find(nItemIndex);
76 if (it != m_Items.end())
77 it->second = DESELECTING;
80void CPWL_ListCtrl::SelectState::Sub(int32_t nBeginIndex, int32_t nEndIndex) {
81 if (nBeginIndex > nEndIndex)
82 std::swap(nBeginIndex, nEndIndex);
84 for (int32_t i = nBeginIndex; i <= nEndIndex; ++i)
89 for (
auto& item : m_Items)
90 item.second = DESELECTING;
94 auto it = m_Items.begin();
95 while (it != m_Items.end()) {
96 if (it->second == DESELECTING)
97 it = m_Items.erase(it);
99 (it++)->second = NORMAL;
110CFX_PointF
CPWL_ListCtrl::InToOut(
const CFX_PointF& point)
const {
112 return CFX_PointF(point.x - (m_ptScrollPos.x - rcPlate.left),
113 point.y - (m_ptScrollPos.y - rcPlate.top));
116CFX_PointF
CPWL_ListCtrl::OutToIn(
const CFX_PointF& point)
const {
118 return CFX_PointF(point.x + (m_ptScrollPos.x - rcPlate.left),
119 point.y + (m_ptScrollPos.y - rcPlate.top));
123 CFX_PointF ptLeftBottom = InToOut(CFX_PointF(rect.left, rect.bottom));
124 CFX_PointF ptRightTop = InToOut(CFX_PointF(rect.right, rect.top));
125 return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
130 CFX_PointF ptLeftBottom = OutToIn(CFX_PointF(rect.left, rect.bottom));
131 CFX_PointF ptRightTop = OutToIn(CFX_PointF(rect.right, rect.top));
132 return CFX_FloatRect(ptLeftBottom.x, ptLeftBottom.y, ptRightTop.x,
136CFX_PointF
CPWL_ListCtrl::InnerToOuter(
const CFX_PointF& point)
const {
137 return CFX_PointF(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
140CFX_PointF
CPWL_ListCtrl::OuterToInner(
const CFX_PointF& point)
const {
141 return CFX_PointF(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
145 CFX_PointF ptLeftTop = InnerToOuter(CFX_PointF(rect.left, rect.top));
146 CFX_PointF ptRightBottom = InnerToOuter(CFX_PointF(rect.right, rect.bottom));
147 return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
152 CFX_PointF ptLeftTop = OuterToInner(CFX_PointF(rect.left, rect.top));
153 CFX_PointF ptRightBottom = OuterToInner(CFX_PointF(rect.right, rect.bottom));
154 return CFX_FloatRect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x,
166 m_SelectState.Sub(nHitIndex);
170 m_SelectState.Add(nHitIndex);
175 m_nFootIndex = nHitIndex;
177 m_SelectState.DeselectAll();
178 m_SelectState.Add(m_nFootIndex, nHitIndex);
181 m_SelectState.DeselectAll();
182 m_SelectState.Add(nHitIndex);
185 m_nFootIndex = nHitIndex;
190 SetSingleSelect(nHitIndex);
193 if (!IsItemVisible(nHitIndex))
205 m_SelectState.Add(m_nFootIndex, nHitIndex);
207 m_SelectState.Sub(m_nFootIndex, nHitIndex);
211 m_SelectState.DeselectAll();
212 m_SelectState.Add(m_nFootIndex, nHitIndex);
218 SetSingleSelect(nHitIndex);
221 if (!IsItemVisible(nHitIndex))
225void CPWL_ListCtrl::OnVK(int32_t nItemIndex,
bool bShift,
bool bCtrl) {
227 if (nItemIndex >= 0 && nItemIndex <
GetCount()) {
230 m_SelectState.DeselectAll();
231 m_SelectState.Add(m_nFootIndex, nItemIndex);
234 m_SelectState.DeselectAll();
235 m_SelectState.Add(nItemIndex);
237 m_nFootIndex = nItemIndex;
243 SetSingleSelect(nItemIndex);
246 if (!IsItemVisible(nItemIndex))
259 OnVK(0, bShift, bCtrl);
267 OnVK(0, bShift, bCtrl);
275 int32_t nIndex = GetLastSelected();
278 if (nFindIndex != nIndex) {
279 OnVK(nFindIndex, bShift, bCtrl);
287 m_ptScrollPos.x = rect.left;
294 return InToOut(GetItemRectInternal(nIndex));
298 if (!IsValid(nIndex))
304 return InnerToOuter(rcItem);
312void CPWL_ListCtrl::SetMultipleSelect(int32_t nItemIndex,
bool bSelected) {
313 if (!IsValid(nItemIndex))
318 SetItemSelect(nItemIndex,
true);
319 InvalidateItem(nItemIndex);
321 SetItemSelect(nItemIndex,
false);
322 InvalidateItem(nItemIndex);
328 if (!IsValid(nItemIndex))
331 if (m_nSelItem != nItemIndex) {
332 if (m_nSelItem >= 0) {
333 SetItemSelect(m_nSelItem,
false);
334 InvalidateItem(m_nSelItem);
337 SetItemSelect(nItemIndex,
true);
338 InvalidateItem(nItemIndex);
339 m_nSelItem = nItemIndex;
344 if (!IsValid(nItemIndex))
348 int32_t nOldIndex = m_nCaretIndex;
350 if (nOldIndex != nItemIndex) {
351 m_nCaretIndex = nItemIndex;
352 InvalidateItem(nOldIndex);
353 InvalidateItem(nItemIndex);
362 if (nItemIndex == -1) {
363 if (!m_bNotifyFlag) {
364 m_bNotifyFlag =
true;
366 if (!m_pNotify->OnInvalidateRect(rcRefresh)) {
369 m_bNotifyFlag =
false;
372 if (!m_bNotifyFlag) {
373 m_bNotifyFlag =
true;
375 rcRefresh
.left -= 1.0f;
378 rcRefresh
.top += 1.0f;
379 if (!m_pNotify->OnInvalidateRect(rcRefresh)) {
382 m_bNotifyFlag =
false;
388 for (
const auto& item : m_SelectState) {
389 if (item.second != SelectState::NORMAL)
390 SetMultipleSelect(item.first, item.second == SelectState::SELECTING);
392 m_SelectState.Done();
396 if (!IsValid(nItemIndex))
400 m_SelectState.Add(nItemIndex);
403 SetSingleSelect(nItemIndex);
411 SetMultipleSelect(nItemIndex,
false);
425 if (!IsValid(nItemIndex))
438 SetScrollPosY(rcItem
.top);
448 if (!m_bNotifyFlag) {
449 m_bNotifyFlag =
true;
450 m_pNotify->OnSetScrollInfoY(rcPlate.bottom, rcPlate.top, rcContent.bottom,
451 rcContent.top, GetFirstHeight(),
453 m_bNotifyFlag =
false;
459 SetScrollPosY(point.y);
477 m_ptScrollPos.y = fy;
481 if (!m_bNotifyFlag) {
482 m_bNotifyFlag =
true;
483 m_pNotify->OnSetScrollPosY(fy);
484 m_bNotifyFlag =
false;
491 return InnerToOuter(m_rcContent);
495 return InToOut(GetContentRectInternal());
500 if (IsValid(nItemIndex - 1))
501 fPosY = m_ListItems[nItemIndex - 1]->GetRect().bottom;
503 for (
const auto& pListItem : m_ListItems) {
504 float fListItemHeight = pListItem->GetItemHeight();
506 CFX_FloatRect(0.0f, fPosY + fListItemHeight, 0.0f, fPosY));
507 fPosY += fListItemHeight;
514 if (IsValid(nIndex)) {
516 SetScrollPosY(rcItem
.top);
521 int32_t nItemIndex = GetItemIndex(GetBTPoint());
522 if (!IsItemVisible(nItemIndex) && IsItemVisible(nItemIndex + 1))
529 CFX_PointF pt = OuterToInner(OutToIn(point));
532 for (
const auto& pListItem : m_ListItems) {
533 CFX_FloatRect rcListItem = pListItem->GetRect();
538 if (pt.y >= rcListItem.top && pt.y < rcListItem.bottom) {
539 return pdfium::base::checked_cast<int32_t>(&pListItem -
540 &m_ListItems.front());
552 return GetItemText(m_nCaretIndex);
553 return GetItemText(m_nSelItem);
557 auto pListItem =
std::make_unique<Item>();
558 pListItem->SetFontMap(m_pFontMap);
559 pListItem->SetFontSize(m_fFontSize);
560 pListItem->SetText(str);
561 m_ListItems.push_back(std::move(pListItem));
565 if (!IsValid(nIndex))
567 return m_ListItems[nIndex]->GetEdit();
571 return fxcrt::CollectionSize<int32_t>(m_ListItems);
575 if (m_ListItems.empty())
577 return m_ListItems.front()->GetItemHeight();
582 for (
const auto& pListItem : m_ListItems) {
583 if (pListItem->IsSelected())
591 for (
auto iter = m_ListItems.rbegin(); iter != m_ListItems.rend(); ++iter) {
592 if ((*iter)->IsSelected())
593 return pdfium::base::checked_cast<int32_t>(&*iter - &m_ListItems.front());
599 int32_t nCircleIndex = nIndex;
601 for (int32_t i = 0; i < sz; i++) {
603 if (nCircleIndex >= sz)
606 if (Item* pListItem = m_ListItems[nCircleIndex].get()) {
616 return IsValid(nIndex) && m_ListItems[nIndex]->IsSelected();
619void CPWL_ListCtrl::SetItemSelect(int32_t nIndex,
bool bSelected) {
621 m_ListItems[nIndex]->SetSelect(bSelected);
625 return fxcrt::IndexInBounds(m_ListItems, nItemIndex);
630 return m_ListItems[nIndex]->GetText();
constexpr CFX_FloatRect(float l, float b, float r, float t)
constexpr CFX_FloatRect()=default
CFX_FloatRect & operator=(const CFX_FloatRect &that)=default
void SetAt(int32_t nWordIndex)
bool GetWord(CPVT_Word &word) const
void OnVK_LEFT(bool bShift, bool bCtrl)
bool OnChar(uint16_t nChar, bool bShift, bool bCtrl)
void SetCaret(int32_t nItemIndex)
void OnVK_UP(bool bShift, bool bCtrl)
void Select(int32_t nItemIndex)
CPWL_EditImpl * GetItemEdit(int32_t nIndex) const
void AddString(const WideString &str)
CFX_FloatRect GetContentRect() const
void Deselect(int32_t nItemIndex)
WideString GetText() const
void SetScrollPos(const CFX_PointF &point)
int32_t FindNext(int32_t nIndex, wchar_t nChar) const
bool IsItemSelected(int32_t nIndex) const
void OnVK_END(bool bShift, bool bCtrl)
void OnVK_DOWN(bool bShift, bool bCtrl)
void ScrollToListItem(int32_t nItemIndex)
CFX_FloatRect GetItemRect(int32_t nIndex) const
void SetTopItem(int32_t nIndex)
bool IsMultipleSel() const
int32_t GetItemIndex(const CFX_PointF &point) const
float GetFirstHeight() const
void OnVK_RIGHT(bool bShift, bool bCtrl)
int32_t GetSelect() const
int32_t GetTopItem() const
int32_t GetFirstSelected() const
void OnVK_HOME(bool bShift, bool bCtrl)
void OnMouseMove(const CFX_PointF &point, bool bShift, bool bCtrl)
void SetPlateRect(const CFX_FloatRect &rect)
void OnMouseDown(const CFX_PointF &point, bool bShift, bool bCtrl)
int32_t FXSYS_towupper(wchar_t c)
#define FXSYS_IsFloatBigger(fa, fb)
#define FXSYS_IsFloatEqual(fa, fb)
#define FXSYS_IsFloatSmaller(fa, fb)