blob: 5549bfb659fd032526386756ff556eb84395963e [file] [log] [blame]
kumarashishg826308d2023-06-23 13:21:22 +00001// Copyright 2014 The PDFium Authors
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -07002// 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 "xfa/fxfa/cxfa_ffpageview.h"
8
9#include <algorithm>
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070010#include <vector>
11
kumarashishg826308d2023-06-23 13:21:22 +000012#include "core/fxcrt/stl_util.h"
13#include "fxjs/gc/container_trace.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070014#include "fxjs/xfa/cjx_object.h"
kumarashishg826308d2023-06-23 13:21:22 +000015#include "third_party/base/check.h"
16#include "third_party/base/containers/contains.h"
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070017#include "xfa/fxfa/cxfa_ffcheckbutton.h"
18#include "xfa/fxfa/cxfa_ffdoc.h"
19#include "xfa/fxfa/cxfa_ffdocview.h"
20#include "xfa/fxfa/cxfa_fffield.h"
21#include "xfa/fxfa/cxfa_ffimageedit.h"
22#include "xfa/fxfa/cxfa_ffpushbutton.h"
23#include "xfa/fxfa/cxfa_ffwidget.h"
24#include "xfa/fxfa/cxfa_fwladapterwidgetmgr.h"
25#include "xfa/fxfa/parser/cxfa_node.h"
26#include "xfa/fxfa/parser/cxfa_traversal.h"
27#include "xfa/fxfa/parser/cxfa_traverse.h"
28
29namespace {
30
31CFX_Matrix GetPageMatrix(const CFX_RectF& docPageRect,
Haibo Huang49cc9302020-04-27 16:14:24 -070032 const FX_RECT& devicePageRect,
kumarashishg826308d2023-06-23 13:21:22 +000033 int32_t iRotate) {
34 DCHECK(iRotate >= 0);
35 DCHECK(iRotate <= 3);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070036
kumarashishg826308d2023-06-23 13:21:22 +000037 CFX_Matrix m;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070038 if (iRotate == 0 || iRotate == 2) {
Haibo Huang49cc9302020-04-27 16:14:24 -070039 m.a *= (float)devicePageRect.Width() / docPageRect.width;
40 m.d *= (float)devicePageRect.Height() / docPageRect.height;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070041 } else {
Haibo Huang49cc9302020-04-27 16:14:24 -070042 m.a *= (float)devicePageRect.Height() / docPageRect.width;
43 m.d *= (float)devicePageRect.Width() / docPageRect.height;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070044 }
45 m.Rotate(iRotate * 1.57079632675f);
46 switch (iRotate) {
47 case 0:
kumarashishg826308d2023-06-23 13:21:22 +000048 m.e = devicePageRect.left;
49 m.f = devicePageRect.top;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070050 break;
51 case 1:
kumarashishg826308d2023-06-23 13:21:22 +000052 m.e = devicePageRect.right;
53 m.f = devicePageRect.top;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070054 break;
55 case 2:
kumarashishg826308d2023-06-23 13:21:22 +000056 m.e = devicePageRect.right;
57 m.f = devicePageRect.bottom;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070058 break;
59 case 3:
kumarashishg826308d2023-06-23 13:21:22 +000060 m.e = devicePageRect.left;
61 m.f = devicePageRect.bottom;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070062 break;
63 default:
64 break;
65 }
66 return m;
67}
68
69bool PageWidgetFilter(CXFA_FFWidget* pWidget,
kumarashishg826308d2023-06-23 13:21:22 +000070 Mask<XFA_WidgetStatus> dwFilter,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070071 bool bTraversal,
Haibo Huang49cc9302020-04-27 16:14:24 -070072 bool bIgnoreRelevant) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070073 CXFA_Node* pNode = pWidget->GetNode();
74
kumarashishg826308d2023-06-23 13:21:22 +000075 if ((dwFilter & XFA_WidgetStatus::kFocused) &&
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070076 (!pNode || pNode->GetElementType() != XFA_Element::Field)) {
77 return false;
78 }
79
Haibo Huang49cc9302020-04-27 16:14:24 -070080 CXFA_ContentLayoutItem* pItem = pWidget->GetLayoutItem();
kumarashishg826308d2023-06-23 13:21:22 +000081 if (bTraversal && pItem->TestStatusBits(XFA_WidgetStatus::kDisabled))
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070082 return false;
Haibo Huang49cc9302020-04-27 16:14:24 -070083 if (bIgnoreRelevant)
kumarashishg826308d2023-06-23 13:21:22 +000084 return pItem->TestStatusBits(XFA_WidgetStatus::kVisible);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070085
kumarashishg826308d2023-06-23 13:21:22 +000086 dwFilter &= Mask<XFA_WidgetStatus>{XFA_WidgetStatus::kVisible,
87 XFA_WidgetStatus::kViewable,
88 XFA_WidgetStatus::kPrintable};
Haibo Huang49cc9302020-04-27 16:14:24 -070089 return pItem->TestStatusBits(dwFilter);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070090}
91
kumarashishg826308d2023-06-23 13:21:22 +000092bool IsLayoutElement(XFA_Element eElement) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070093 switch (eElement) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -070094 case XFA_Element::Area:
95 case XFA_Element::Subform:
96 case XFA_Element::ExclGroup:
97 case XFA_Element::SubformSet:
98 case XFA_Element::PageArea:
99 case XFA_Element::Form:
100 return true;
101 default:
102 return false;
103 }
104}
105
kumarashishg826308d2023-06-23 13:21:22 +0000106CXFA_Document* GetDocForPageView(const CXFA_FFPageView* view) {
107 return view->GetDocView()->GetDoc()->GetXFADoc();
108}
109
110bool IsDocVersionBelow205(const CXFA_Document* doc) {
111 return doc->GetCurVersionMode() < XFA_VERSION_205;
112}
113
114bool EnsureWidgetLoadedIfVisible(CXFA_FFWidget* pWidget) {
115 if (!pWidget->IsLoaded() &&
116 pWidget->GetLayoutItem()->TestStatusBits(XFA_WidgetStatus::kVisible)) {
117 if (!pWidget->LoadWidget())
118 return false;
119 }
120 return true;
121}
122
123CXFA_FFWidget* LoadedWidgetFromLayoutItem(CXFA_LayoutItem* pLayoutItem) {
124 CXFA_FFWidget* pWidget = CXFA_FFWidget::FromLayoutItem(pLayoutItem);
125 if (!pWidget)
126 return nullptr;
127
128 EnsureWidgetLoadedIfVisible(pWidget);
129 return pWidget;
130}
131
132CXFA_FFWidget* FilteredLoadedWidgetFromLayoutItem(
133 CXFA_LayoutItem* pLayoutItem,
134 Mask<XFA_WidgetStatus> dwFilter,
135 bool bIgnoreRelevant) {
136 CXFA_FFWidget* pWidget = CXFA_FFWidget::FromLayoutItem(pLayoutItem);
137 if (!pWidget)
138 return nullptr;
139
140 if (!PageWidgetFilter(pWidget, dwFilter, false, bIgnoreRelevant))
141 return nullptr;
142
143 if (!EnsureWidgetLoadedIfVisible(pWidget))
144 return nullptr;
145
146 return pWidget;
147}
148
149class CXFA_TabParam {
150 public:
151 CXFA_TabParam() = default;
152 explicit CXFA_TabParam(CXFA_FFWidget* pWidget)
153 : m_pItem(pWidget->GetLayoutItem()) {}
154 CXFA_TabParam(const CXFA_TabParam&) = delete;
155 CXFA_TabParam(CXFA_TabParam&&) noexcept = default;
156 ~CXFA_TabParam() = default;
157
158 CXFA_TabParam& operator=(const CXFA_TabParam&) = delete;
159 CXFA_TabParam& operator=(CXFA_TabParam&&) noexcept = default;
160
161 CXFA_FFWidget* GetWidget() const { return m_pItem->GetFFWidget(); }
162 const std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>>& GetChildren()
163 const {
164 return m_Children;
165 }
166 void ClearChildren() { m_Children.clear(); }
167 void AppendTabParam(const CXFA_TabParam* pParam) {
168 m_Children.push_back(pParam->m_pItem);
169 m_Children.insert(m_Children.end(), pParam->m_Children.begin(),
170 pParam->m_Children.end());
171 }
172
173 private:
174 cppgc::Persistent<CXFA_ContentLayoutItem> m_pItem;
175 std::vector<cppgc::Persistent<CXFA_ContentLayoutItem>> m_Children;
176};
177
178void OrderContainer(CXFA_LayoutItemIterator* sIterator,
179 CXFA_LayoutItem* pViewItem,
180 CXFA_TabParam* pContainer,
181 bool* bCurrentItem,
182 bool* bContentArea,
183 bool bMasterPage) {
184 std::vector<CXFA_TabParam> tabParams;
185 CXFA_LayoutItem* pSearchItem = sIterator->MoveToNext();
186 while (pSearchItem) {
187 if (!pSearchItem->IsContentLayoutItem()) {
188 *bContentArea = true;
189 pSearchItem = sIterator->MoveToNext();
190 continue;
191 }
192 if (bMasterPage && *bContentArea) {
193 break;
194 }
195 if (bMasterPage || *bContentArea) {
196 CXFA_FFWidget* hWidget = LoadedWidgetFromLayoutItem(pSearchItem);
197 if (!hWidget) {
198 pSearchItem = sIterator->MoveToNext();
199 continue;
200 }
201 if (pViewItem && (pSearchItem->GetParent() != pViewItem)) {
202 *bCurrentItem = true;
203 break;
204 }
205 tabParams.emplace_back(hWidget);
206 if (IsLayoutElement(pSearchItem->GetFormNode()->GetElementType())) {
207 OrderContainer(sIterator, pSearchItem, &tabParams.back(), bCurrentItem,
208 bContentArea, bMasterPage);
209 }
210 }
211 if (*bCurrentItem) {
212 pSearchItem = sIterator->GetCurrent();
213 *bCurrentItem = false;
214 } else {
215 pSearchItem = sIterator->MoveToNext();
216 }
217 }
218 std::sort(tabParams.begin(), tabParams.end(),
219 [](const CXFA_TabParam& arg1, const CXFA_TabParam& arg2) {
220 const CFX_RectF& rt1 = arg1.GetWidget()->GetWidgetRect();
221 const CFX_RectF& rt2 = arg2.GetWidget()->GetWidgetRect();
222 if (rt1.top - rt2.top >= kXFAWidgetPrecision)
223 return rt1.top < rt2.top;
224 return rt1.left < rt2.left;
225 });
226 for (const auto& param : tabParams)
227 pContainer->AppendTabParam(&param);
228}
229
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700230} // namespace
231
232CXFA_FFPageView::CXFA_FFPageView(CXFA_FFDocView* pDocView, CXFA_Node* pPageArea)
Haibo Huang49cc9302020-04-27 16:14:24 -0700233 : m_pPageArea(pPageArea), m_pDocView(pDocView) {}
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700234
kumarashishg826308d2023-06-23 13:21:22 +0000235CXFA_FFPageView::~CXFA_FFPageView() = default;
236
237void CXFA_FFPageView::Trace(cppgc::Visitor* visitor) const {
238 visitor->Trace(m_pPageArea);
239 visitor->Trace(m_pDocView);
240 visitor->Trace(m_pLayoutItem);
241}
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700242
243CXFA_FFDocView* CXFA_FFPageView::GetDocView() const {
kumarashishg826308d2023-06-23 13:21:22 +0000244 return m_pDocView;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700245}
246
247CFX_RectF CXFA_FFPageView::GetPageViewRect() const {
kumarashishg826308d2023-06-23 13:21:22 +0000248 auto* pItem = GetLayoutItem();
249 if (!pItem)
250 return CFX_RectF();
251
252 return CFX_RectF(0, 0, pItem->GetPageSize());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700253}
254
Haibo Huang49cc9302020-04-27 16:14:24 -0700255CFX_Matrix CXFA_FFPageView::GetDisplayMatrix(const FX_RECT& rtDisp,
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700256 int32_t iRotate) const {
kumarashishg826308d2023-06-23 13:21:22 +0000257 auto* pItem = GetLayoutItem();
258 if (!pItem)
259 return CFX_Matrix();
260
261 return GetPageMatrix(CFX_RectF(0, 0, pItem->GetPageSize()), rtDisp, iRotate);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700262}
263
kumarashishg826308d2023-06-23 13:21:22 +0000264CXFA_FFWidget::IteratorIface* CXFA_FFPageView::CreateGCedTraverseWidgetIterator(
265 Mask<XFA_WidgetStatus> dwWidgetFilter) {
266 return cppgc::MakeGarbageCollected<CXFA_FFTabOrderPageWidgetIterator>(
267 GetDocView()->GetDoc()->GetHeap()->GetAllocationHandle(), this,
268 dwWidgetFilter);
Haibo Huang49cc9302020-04-27 16:14:24 -0700269}
270
kumarashishg826308d2023-06-23 13:21:22 +0000271CXFA_FFPageWidgetIterator::CXFA_FFPageWidgetIterator(
272 CXFA_FFPageView* pPageView,
273 Mask<XFA_WidgetStatus> dwFilter)
274 : m_sIterator(pPageView->GetLayoutItem()),
Haibo Huang49cc9302020-04-27 16:14:24 -0700275 m_dwFilter(dwFilter),
kumarashishg826308d2023-06-23 13:21:22 +0000276 m_bIgnoreRelevant(IsDocVersionBelow205(GetDocForPageView(pPageView))) {}
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700277
kumarashishg826308d2023-06-23 13:21:22 +0000278CXFA_FFPageWidgetIterator::~CXFA_FFPageWidgetIterator() = default;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700279
280CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToFirst() {
281 m_sIterator.Reset();
282 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent(); pLayoutItem;
283 pLayoutItem = m_sIterator.MoveToNext()) {
kumarashishg826308d2023-06-23 13:21:22 +0000284 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
285 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
286 if (hWidget)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700287 return hWidget;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700288 }
289 return nullptr;
290}
291
292CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToLast() {
293 m_sIterator.SetCurrent(nullptr);
294 return MoveToPrevious();
295}
296
297CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToNext() {
298 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToNext(); pLayoutItem;
299 pLayoutItem = m_sIterator.MoveToNext()) {
kumarashishg826308d2023-06-23 13:21:22 +0000300 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
301 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
302 if (hWidget)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700303 return hWidget;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700304 }
305 return nullptr;
306}
307
308CXFA_FFWidget* CXFA_FFPageWidgetIterator::MoveToPrevious() {
309 for (CXFA_LayoutItem* pLayoutItem = m_sIterator.MoveToPrev(); pLayoutItem;
310 pLayoutItem = m_sIterator.MoveToPrev()) {
kumarashishg826308d2023-06-23 13:21:22 +0000311 CXFA_FFWidget* hWidget = FilteredLoadedWidgetFromLayoutItem(
312 pLayoutItem, m_dwFilter, m_bIgnoreRelevant);
313 if (hWidget)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700314 return hWidget;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700315 }
316 return nullptr;
317}
318
319CXFA_FFWidget* CXFA_FFPageWidgetIterator::GetCurrentWidget() {
320 CXFA_LayoutItem* pLayoutItem = m_sIterator.GetCurrent();
kumarashishg826308d2023-06-23 13:21:22 +0000321 return pLayoutItem ? CXFA_FFWidget::FromLayoutItem(pLayoutItem) : nullptr;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700322}
323
Haibo Huang49cc9302020-04-27 16:14:24 -0700324bool CXFA_FFPageWidgetIterator::SetCurrentWidget(CXFA_FFWidget* pWidget) {
325 return pWidget && m_sIterator.SetCurrent(pWidget->GetLayoutItem());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700326}
327
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700328CXFA_FFTabOrderPageWidgetIterator::CXFA_FFTabOrderPageWidgetIterator(
329 CXFA_FFPageView* pPageView,
kumarashishg826308d2023-06-23 13:21:22 +0000330 Mask<XFA_WidgetStatus> dwFilter)
331 : m_pPageViewLayout(pPageView->GetLayoutItem()),
332 m_dwFilter(dwFilter),
333 m_bIgnoreRelevant(IsDocVersionBelow205(GetDocForPageView(pPageView))) {
334 CreateTabOrderWidgetArray();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700335}
336
kumarashishg826308d2023-06-23 13:21:22 +0000337CXFA_FFTabOrderPageWidgetIterator::~CXFA_FFTabOrderPageWidgetIterator() =
338 default;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700339
kumarashishg826308d2023-06-23 13:21:22 +0000340void CXFA_FFTabOrderPageWidgetIterator::Trace(cppgc::Visitor* visitor) const {
341 visitor->Trace(m_pPageViewLayout);
342 ContainerTrace(visitor, m_TabOrderWidgetArray);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700343}
344
345CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToFirst() {
kumarashishg826308d2023-06-23 13:21:22 +0000346 for (int32_t i = 0; i < fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray);
347 i++) {
348 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
349 true, m_bIgnoreRelevant)) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700350 m_iCurWidget = i;
kumarashishg826308d2023-06-23 13:21:22 +0000351 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700352 }
353 }
354 return nullptr;
355}
356
357CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToLast() {
kumarashishg826308d2023-06-23 13:21:22 +0000358 for (int32_t i = fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray) - 1;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700359 i >= 0; i--) {
kumarashishg826308d2023-06-23 13:21:22 +0000360 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
361 true, m_bIgnoreRelevant)) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700362 m_iCurWidget = i;
kumarashishg826308d2023-06-23 13:21:22 +0000363 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700364 }
365 }
366 return nullptr;
367}
368
369CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToNext() {
370 for (int32_t i = m_iCurWidget + 1;
kumarashishg826308d2023-06-23 13:21:22 +0000371 i < fxcrt::CollectionSize<int32_t>(m_TabOrderWidgetArray); i++) {
372 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
373 true, m_bIgnoreRelevant)) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700374 m_iCurWidget = i;
kumarashishg826308d2023-06-23 13:21:22 +0000375 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700376 }
377 }
378 m_iCurWidget = -1;
379 return nullptr;
380}
381
382CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::MoveToPrevious() {
383 for (int32_t i = m_iCurWidget - 1; i >= 0; i--) {
kumarashishg826308d2023-06-23 13:21:22 +0000384 if (PageWidgetFilter(m_TabOrderWidgetArray[i]->GetFFWidget(), m_dwFilter,
385 true, m_bIgnoreRelevant)) {
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700386 m_iCurWidget = i;
kumarashishg826308d2023-06-23 13:21:22 +0000387 return m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700388 }
389 }
390 m_iCurWidget = -1;
391 return nullptr;
392}
393
394CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetCurrentWidget() {
kumarashishg826308d2023-06-23 13:21:22 +0000395 return m_iCurWidget >= 0 ? m_TabOrderWidgetArray[m_iCurWidget]->GetFFWidget()
Haibo Huang49cc9302020-04-27 16:14:24 -0700396 : nullptr;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700397}
398
399bool CXFA_FFTabOrderPageWidgetIterator::SetCurrentWidget(
400 CXFA_FFWidget* hWidget) {
401 auto it = std::find(m_TabOrderWidgetArray.begin(),
kumarashishg826308d2023-06-23 13:21:22 +0000402 m_TabOrderWidgetArray.end(), hWidget->GetLayoutItem());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700403 if (it == m_TabOrderWidgetArray.end())
404 return false;
405
kumarashishg826308d2023-06-23 13:21:22 +0000406 m_iCurWidget =
407 pdfium::base::checked_cast<int32_t>(it - m_TabOrderWidgetArray.begin());
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700408 return true;
409}
410
411CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::GetTraverseWidget(
412 CXFA_FFWidget* pWidget) {
413 CXFA_Traversal* pTraversal = pWidget->GetNode()->GetChild<CXFA_Traversal>(
414 0, XFA_Element::Traversal, false);
415 if (pTraversal) {
416 CXFA_Traverse* pTraverse =
417 pTraversal->GetChild<CXFA_Traverse>(0, XFA_Element::Traverse, false);
418 if (pTraverse) {
kumarashishg826308d2023-06-23 13:21:22 +0000419 absl::optional<WideString> traverseWidgetName =
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700420 pTraverse->JSObject()->TryAttribute(XFA_Attribute::Ref, true);
kumarashishg826308d2023-06-23 13:21:22 +0000421 if (traverseWidgetName.has_value())
422 return FindWidgetByName(traverseWidgetName.value(), pWidget);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700423 }
424 }
425 return nullptr;
426}
427CXFA_FFWidget* CXFA_FFTabOrderPageWidgetIterator::FindWidgetByName(
428 const WideString& wsWidgetName,
429 CXFA_FFWidget* pRefWidget) {
430 return pRefWidget->GetDocView()->GetWidgetByName(wsWidgetName, pRefWidget);
431}
432
433void CXFA_FFTabOrderPageWidgetIterator::CreateTabOrderWidgetArray() {
434 m_TabOrderWidgetArray.clear();
435
kumarashishg826308d2023-06-23 13:21:22 +0000436 const std::vector<CXFA_ContentLayoutItem*> items =
437 CreateSpaceOrderLayoutItems();
438 if (items.empty())
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700439 return;
440
kumarashishg826308d2023-06-23 13:21:22 +0000441 CXFA_ContentLayoutItem* item = items[0];
442 while (m_TabOrderWidgetArray.size() < items.size()) {
443 if (!pdfium::Contains(m_TabOrderWidgetArray, item)) {
444 m_TabOrderWidgetArray.emplace_back(item);
445 CXFA_Node* node = item->GetFFWidget()->GetNode();
446 if (node->GetFFWidgetType() == XFA_FFWidgetType::kExclGroup) {
447 auto it = std::find(items.begin(), items.end(), item);
448 size_t index = it != items.end() ? it - items.begin() + 1 : 0;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700449 while (true) {
kumarashishg826308d2023-06-23 13:21:22 +0000450 CXFA_FFWidget* radio = items[index % items.size()]->GetFFWidget();
451 if (radio->GetNode()->GetExclGroupIfExists() != node)
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700452 break;
kumarashishg826308d2023-06-23 13:21:22 +0000453 if (!pdfium::Contains(m_TabOrderWidgetArray, item))
454 m_TabOrderWidgetArray.emplace_back(radio->GetLayoutItem());
455 ++index;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700456 }
457 }
kumarashishg826308d2023-06-23 13:21:22 +0000458 CXFA_FFWidget* next_widget = GetTraverseWidget(item->GetFFWidget());
459 if (next_widget) {
460 item = next_widget->GetLayoutItem();
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700461 continue;
462 }
463 }
kumarashishg826308d2023-06-23 13:21:22 +0000464 auto it = std::find(items.begin(), items.end(), item);
465 size_t index = it != items.end() ? it - items.begin() + 1 : 0;
466 item = items[index % items.size()];
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700467 }
468}
469
kumarashishg826308d2023-06-23 13:21:22 +0000470std::vector<CXFA_ContentLayoutItem*>
471CXFA_FFTabOrderPageWidgetIterator::CreateSpaceOrderLayoutItems() {
472 std::vector<CXFA_ContentLayoutItem*> items;
473 CXFA_LayoutItemIterator sIterator(m_pPageViewLayout.Get());
474 CXFA_TabParam tabparam;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700475 bool bCurrentItem = false;
476 bool bContentArea = false;
kumarashishg826308d2023-06-23 13:21:22 +0000477 OrderContainer(&sIterator, nullptr, &tabparam, &bCurrentItem, &bContentArea,
478 false);
479 items.reserve(tabparam.GetChildren().size());
480 for (const auto& layout_item : tabparam.GetChildren())
481 items.push_back(layout_item);
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700482
483 sIterator.Reset();
484 bCurrentItem = false;
485 bContentArea = false;
kumarashishg826308d2023-06-23 13:21:22 +0000486 tabparam.ClearChildren();
487 OrderContainer(&sIterator, nullptr, &tabparam, &bCurrentItem, &bContentArea,
488 true);
489 for (const auto& layout_item : tabparam.GetChildren())
490 items.push_back(layout_item);
491
492 return items;
Philip P. Moltmannd904c1e2018-03-19 09:26:45 -0700493}