xref: /aosp_15_r20/external/pdfium/xfa/fwl/cfwl_widgetmgr.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2014 The PDFium Authors
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 "xfa/fwl/cfwl_widgetmgr.h"
8 
9 #include "build/build_config.h"
10 #include "fxjs/gc/container_trace.h"
11 #include "third_party/base/check.h"
12 #include "xfa/fwl/cfwl_app.h"
13 #include "xfa/fwl/cfwl_message.h"
14 #include "xfa/fwl/cfwl_notedriver.h"
15 #include "xfa/fwl/cfwl_pushbutton.h"
16 
CFWL_WidgetMgr(AdapterIface * pAdapter,CFWL_App * pApp)17 CFWL_WidgetMgr::CFWL_WidgetMgr(AdapterIface* pAdapter, CFWL_App* pApp)
18     : m_pAdapter(pAdapter), m_pApp(pApp) {
19   DCHECK(m_pAdapter);
20   m_mapWidgetItem[nullptr] = cppgc::MakeGarbageCollected<Item>(
21       pApp->GetHeap()->GetAllocationHandle(), nullptr);
22 }
23 
24 CFWL_WidgetMgr::~CFWL_WidgetMgr() = default;
25 
Trace(cppgc::Visitor * visitor) const26 void CFWL_WidgetMgr::Trace(cppgc::Visitor* visitor) const {
27   visitor->Trace(m_pApp);
28   visitor->Trace(m_pAdapter);
29   ContainerTrace(visitor, m_mapWidgetItem);
30 }
31 
GetParentWidget(const CFWL_Widget * pWidget) const32 CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(const CFWL_Widget* pWidget) const {
33   Item* pItem = GetWidgetMgrItem(pWidget);
34   if (!pItem)
35     return nullptr;
36 
37   Item* pParent = pItem->GetParent();
38   return pParent ? pParent->pWidget : nullptr;
39 }
40 
GetPriorSiblingWidget(CFWL_Widget * pWidget) const41 CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
42   Item* pItem = GetWidgetMgrItem(pWidget);
43   if (!pItem)
44     return nullptr;
45 
46   Item* pSibling = pItem->GetPrevSibling();
47   return pSibling ? pSibling->pWidget : nullptr;
48 }
49 
GetNextSiblingWidget(CFWL_Widget * pWidget) const50 CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
51   Item* pItem = GetWidgetMgrItem(pWidget);
52   if (!pItem)
53     return nullptr;
54 
55   Item* pSibling = pItem->GetNextSibling();
56   return pSibling ? pSibling->pWidget : nullptr;
57 }
58 
GetFirstChildWidget(CFWL_Widget * pWidget) const59 CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
60   Item* pItem = GetWidgetMgrItem(pWidget);
61   if (!pItem)
62     return nullptr;
63 
64   Item* pChild = pItem->GetFirstChild();
65   return pChild ? pChild->pWidget : nullptr;
66 }
67 
GetLastChildWidget(CFWL_Widget * pWidget) const68 CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
69   Item* pItem = GetWidgetMgrItem(pWidget);
70   if (!pItem)
71     return nullptr;
72 
73   Item* pChild = pItem->GetLastChild();
74   return pChild ? pChild->pWidget : nullptr;
75 }
76 
RepaintWidget(CFWL_Widget * pWidget,const CFX_RectF & rect)77 void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
78                                    const CFX_RectF& rect) {
79   CFWL_Widget* pNative = pWidget;
80   CFX_RectF transformedRect = rect;
81   CFWL_Widget* pOuter = pWidget->GetOuter();
82   while (pOuter) {
83     CFX_RectF rtTemp = pNative->GetWidgetRect();
84     transformedRect.left += rtTemp.left;
85     transformedRect.top += rtTemp.top;
86     pNative = pOuter;
87     pOuter = pOuter->GetOuter();
88   }
89   m_pAdapter->RepaintWidget(pNative);
90 }
91 
InsertWidget(CFWL_Widget * pParent,CFWL_Widget * pChild)92 void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
93   Item* pParentItem = GetWidgetMgrItem(pParent);
94   if (!pParentItem) {
95     pParentItem = CreateWidgetMgrItem(pParent);
96     GetWidgetMgrRootItem()->AppendLastChild(pParentItem);
97   }
98   Item* pChildItem = GetWidgetMgrItem(pChild);
99   if (!pChildItem)
100     pChildItem = CreateWidgetMgrItem(pChild);
101   pParentItem->AppendLastChild(pChildItem);
102 }
103 
RemoveWidget(CFWL_Widget * pWidget)104 void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
105   DCHECK(pWidget);
106   Item* pItem = GetWidgetMgrItem(pWidget);
107   if (!pItem)
108     return;
109 
110   while (pItem->GetFirstChild())
111     RemoveWidget(pItem->GetFirstChild()->pWidget);
112 
113   pItem->RemoveSelfIfParented();
114   m_mapWidgetItem.erase(pWidget);
115 }
116 
GetWidgetAtPoint(CFWL_Widget * parent,const CFX_PointF & point) const117 CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
118                                               const CFX_PointF& point) const {
119   if (!parent)
120     return nullptr;
121 
122   CFWL_Widget* child = GetLastChildWidget(parent);
123   while (child) {
124     if (child->IsVisible()) {
125       CFX_PointF pos = parent->GetMatrix().GetInverse().Transform(point);
126       CFX_RectF bounds = child->GetWidgetRect();
127       if (bounds.Contains(pos)) {
128         pos -= bounds.TopLeft();
129         return GetWidgetAtPoint(child, pos);
130       }
131     }
132     child = GetPriorSiblingWidget(child);
133   }
134   return parent;
135 }
136 
GetDefaultButton(CFWL_Widget * pParent) const137 CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
138   if (pParent->GetClassID() == FWL_Type::PushButton &&
139       (pParent->GetStates() & FWL_STATE_PSB_Default)) {
140     return pParent;
141   }
142 
143   CFWL_Widget* child = GetFirstChildWidget(pParent);
144   while (child) {
145     if (child->GetClassID() == FWL_Type::PushButton &&
146         (child->GetStates() & FWL_STATE_PSB_Default)) {
147       return child;
148     }
149     if (CFWL_Widget* find = GetDefaultButton(child))
150       return find;
151 
152     child = GetNextSiblingWidget(child);
153   }
154   return nullptr;
155 }
156 
GetWidgetMgrRootItem() const157 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrRootItem() const {
158   return GetWidgetMgrItem(nullptr);
159 }
160 
GetWidgetMgrItem(const CFWL_Widget * pWidget) const161 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
162     const CFWL_Widget* pWidget) const {
163   auto it = m_mapWidgetItem.find(pWidget);
164   return it != m_mapWidgetItem.end() ? it->second : nullptr;
165 }
166 
CreateWidgetMgrItem(CFWL_Widget * pWidget)167 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::CreateWidgetMgrItem(
168     CFWL_Widget* pWidget) {
169   auto* pItem = cppgc::MakeGarbageCollected<Item>(
170       m_pApp->GetHeap()->GetAllocationHandle(), pWidget);
171   m_mapWidgetItem[pWidget] = pItem;
172   return pItem;
173 }
174 
GetAdapterPopupPos(CFWL_Widget * pWidget,float fMinHeight,float fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF * pPopupRect) const175 void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
176                                         float fMinHeight,
177                                         float fMaxHeight,
178                                         const CFX_RectF& rtAnchor,
179                                         CFX_RectF* pPopupRect) const {
180   m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor,
181                           pPopupRect);
182 }
183 
OnProcessMessageToForm(CFWL_Message * pMessage)184 void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
185   CFWL_Widget* pDstWidget = pMessage->GetDstTarget();
186   if (!pDstWidget)
187     return;
188 
189   CFWL_NoteDriver* pNoteDriver = pDstWidget->GetFWLApp()->GetNoteDriver();
190   pNoteDriver->ProcessMessage(pMessage);
191 }
192 
OnDrawWidget(CFWL_Widget * pWidget,CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)193 void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
194                                   CFGAS_GEGraphics* pGraphics,
195                                   const CFX_Matrix& matrix) {
196   if (!pWidget || !pGraphics)
197     return;
198 
199   pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix);
200 
201   CFX_RectF clipBounds = pGraphics->GetClipRect();
202   if (!clipBounds.IsEmpty())
203     DrawChildren(pWidget, clipBounds, pGraphics, matrix);
204 }
205 
DrawChildren(CFWL_Widget * parent,const CFX_RectF & rtClip,CFGAS_GEGraphics * pGraphics,const CFX_Matrix & mtMatrix)206 void CFWL_WidgetMgr::DrawChildren(CFWL_Widget* parent,
207                                   const CFX_RectF& rtClip,
208                                   CFGAS_GEGraphics* pGraphics,
209                                   const CFX_Matrix& mtMatrix) {
210   if (!parent)
211     return;
212 
213   CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
214   while (pNextChild) {
215     CFWL_Widget* child = pNextChild;
216     pNextChild = GetNextSiblingWidget(child);
217     if (!child->IsVisible())
218       continue;
219 
220     CFX_RectF rtWidget = child->GetWidgetRect();
221     if (rtWidget.IsEmpty())
222       continue;
223 
224     CFX_Matrix widgetMatrix;
225     CFX_RectF clipBounds(rtWidget);
226     widgetMatrix.Concat(mtMatrix);
227     widgetMatrix.TranslatePrepend(rtWidget.left, rtWidget.top);
228 
229     if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate())
230       pDelegate->OnDrawWidget(pGraphics, widgetMatrix);
231 
232     DrawChildren(child, clipBounds, pGraphics, widgetMatrix);
233   }
234 }
235 
Item(CFWL_Widget * widget)236 CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) : pWidget(widget) {}
237 
238 CFWL_WidgetMgr::Item::~Item() = default;
239 
Trace(cppgc::Visitor * visitor) const240 void CFWL_WidgetMgr::Item::Trace(cppgc::Visitor* visitor) const {
241   GCedTreeNode<Item>::Trace(visitor);
242   visitor->Trace(pWidget);
243 }
244