• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "core/fxcrt/check.h"
11 #include "fxjs/gc/container_trace.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 
17 namespace pdfium {
18 
CFWL_WidgetMgr(AdapterIface * pAdapter,CFWL_App * pApp)19 CFWL_WidgetMgr::CFWL_WidgetMgr(AdapterIface* pAdapter, CFWL_App* pApp)
20     : m_pAdapter(pAdapter), m_pApp(pApp) {
21   DCHECK(m_pAdapter);
22   m_mapWidgetItem[nullptr] = cppgc::MakeGarbageCollected<Item>(
23       pApp->GetHeap()->GetAllocationHandle(), nullptr);
24 }
25 
26 CFWL_WidgetMgr::~CFWL_WidgetMgr() = default;
27 
Trace(cppgc::Visitor * visitor) const28 void CFWL_WidgetMgr::Trace(cppgc::Visitor* visitor) const {
29   visitor->Trace(m_pApp);
30   visitor->Trace(m_pAdapter);
31   ContainerTrace(visitor, m_mapWidgetItem);
32 }
33 
GetParentWidget(const CFWL_Widget * pWidget) const34 CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(const CFWL_Widget* pWidget) const {
35   Item* pItem = GetWidgetMgrItem(pWidget);
36   if (!pItem)
37     return nullptr;
38 
39   Item* pParent = pItem->GetParent();
40   return pParent ? pParent->pWidget : nullptr;
41 }
42 
GetPriorSiblingWidget(CFWL_Widget * pWidget) const43 CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
44   Item* pItem = GetWidgetMgrItem(pWidget);
45   if (!pItem)
46     return nullptr;
47 
48   Item* pSibling = pItem->GetPrevSibling();
49   return pSibling ? pSibling->pWidget : nullptr;
50 }
51 
GetNextSiblingWidget(CFWL_Widget * pWidget) const52 CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
53   Item* pItem = GetWidgetMgrItem(pWidget);
54   if (!pItem)
55     return nullptr;
56 
57   Item* pSibling = pItem->GetNextSibling();
58   return pSibling ? pSibling->pWidget : nullptr;
59 }
60 
GetFirstChildWidget(CFWL_Widget * pWidget) const61 CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
62   Item* pItem = GetWidgetMgrItem(pWidget);
63   if (!pItem)
64     return nullptr;
65 
66   Item* pChild = pItem->GetFirstChild();
67   return pChild ? pChild->pWidget : nullptr;
68 }
69 
GetLastChildWidget(CFWL_Widget * pWidget) const70 CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
71   Item* pItem = GetWidgetMgrItem(pWidget);
72   if (!pItem)
73     return nullptr;
74 
75   Item* pChild = pItem->GetLastChild();
76   return pChild ? pChild->pWidget : nullptr;
77 }
78 
RepaintWidget(CFWL_Widget * pWidget,const CFX_RectF & rect)79 void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
80                                    const CFX_RectF& rect) {
81   CFWL_Widget* pNative = pWidget;
82   CFX_RectF transformedRect = rect;
83   CFWL_Widget* pOuter = pWidget->GetOuter();
84   while (pOuter) {
85     CFX_RectF rtTemp = pNative->GetWidgetRect();
86     transformedRect.left += rtTemp.left;
87     transformedRect.top += rtTemp.top;
88     pNative = pOuter;
89     pOuter = pOuter->GetOuter();
90   }
91   m_pAdapter->RepaintWidget(pNative);
92 }
93 
InsertWidget(CFWL_Widget * pParent,CFWL_Widget * pChild)94 void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
95   Item* pParentItem = GetWidgetMgrItem(pParent);
96   if (!pParentItem) {
97     pParentItem = CreateWidgetMgrItem(pParent);
98     GetWidgetMgrRootItem()->AppendLastChild(pParentItem);
99   }
100   Item* pChildItem = GetWidgetMgrItem(pChild);
101   if (!pChildItem)
102     pChildItem = CreateWidgetMgrItem(pChild);
103   pParentItem->AppendLastChild(pChildItem);
104 }
105 
RemoveWidget(CFWL_Widget * pWidget)106 void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
107   DCHECK(pWidget);
108   Item* pItem = GetWidgetMgrItem(pWidget);
109   if (!pItem)
110     return;
111 
112   while (pItem->GetFirstChild())
113     RemoveWidget(pItem->GetFirstChild()->pWidget);
114 
115   pItem->RemoveSelfIfParented();
116   m_mapWidgetItem.erase(pWidget);
117 }
118 
GetWidgetAtPoint(CFWL_Widget * parent,const CFX_PointF & point) const119 CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
120                                               const CFX_PointF& point) const {
121   if (!parent)
122     return nullptr;
123 
124   CFWL_Widget* child = GetLastChildWidget(parent);
125   while (child) {
126     if (child->IsVisible()) {
127       CFX_PointF pos = parent->GetMatrix().GetInverse().Transform(point);
128       CFX_RectF bounds = child->GetWidgetRect();
129       if (bounds.Contains(pos)) {
130         pos -= bounds.TopLeft();
131         return GetWidgetAtPoint(child, pos);
132       }
133     }
134     child = GetPriorSiblingWidget(child);
135   }
136   return parent;
137 }
138 
GetDefaultButton(CFWL_Widget * pParent) const139 CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const {
140   if (pParent->GetClassID() == FWL_Type::PushButton &&
141       (pParent->GetStates() & FWL_STATE_PSB_Default)) {
142     return pParent;
143   }
144 
145   CFWL_Widget* child = GetFirstChildWidget(pParent);
146   while (child) {
147     if (child->GetClassID() == FWL_Type::PushButton &&
148         (child->GetStates() & FWL_STATE_PSB_Default)) {
149       return child;
150     }
151     if (CFWL_Widget* find = GetDefaultButton(child))
152       return find;
153 
154     child = GetNextSiblingWidget(child);
155   }
156   return nullptr;
157 }
158 
GetWidgetMgrRootItem() const159 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrRootItem() const {
160   return GetWidgetMgrItem(nullptr);
161 }
162 
GetWidgetMgrItem(const CFWL_Widget * pWidget) const163 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
164     const CFWL_Widget* pWidget) const {
165   auto it = m_mapWidgetItem.find(pWidget);
166   return it != m_mapWidgetItem.end() ? it->second : nullptr;
167 }
168 
CreateWidgetMgrItem(CFWL_Widget * pWidget)169 CFWL_WidgetMgr::Item* CFWL_WidgetMgr::CreateWidgetMgrItem(
170     CFWL_Widget* pWidget) {
171   auto* pItem = cppgc::MakeGarbageCollected<Item>(
172       m_pApp->GetHeap()->GetAllocationHandle(), pWidget);
173   m_mapWidgetItem[pWidget] = pItem;
174   return pItem;
175 }
176 
GetAdapterPopupPos(CFWL_Widget * pWidget,float fMinHeight,float fMaxHeight,const CFX_RectF & rtAnchor,CFX_RectF * pPopupRect) const177 void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
178                                         float fMinHeight,
179                                         float fMaxHeight,
180                                         const CFX_RectF& rtAnchor,
181                                         CFX_RectF* pPopupRect) const {
182   m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor,
183                           pPopupRect);
184 }
185 
OnProcessMessageToForm(CFWL_Message * pMessage)186 void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
187   CFWL_Widget* pDstWidget = pMessage->GetDstTarget();
188   if (!pDstWidget)
189     return;
190 
191   CFWL_NoteDriver* pNoteDriver = pDstWidget->GetFWLApp()->GetNoteDriver();
192   pNoteDriver->ProcessMessage(pMessage);
193 }
194 
OnDrawWidget(CFWL_Widget * pWidget,CFGAS_GEGraphics * pGraphics,const CFX_Matrix & matrix)195 void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
196                                   CFGAS_GEGraphics* pGraphics,
197                                   const CFX_Matrix& matrix) {
198   if (!pWidget || !pGraphics)
199     return;
200 
201   pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix);
202 
203   CFX_RectF clipBounds = pGraphics->GetClipRect();
204   if (!clipBounds.IsEmpty())
205     DrawChildren(pWidget, clipBounds, pGraphics, matrix);
206 }
207 
DrawChildren(CFWL_Widget * parent,const CFX_RectF & rtClip,CFGAS_GEGraphics * pGraphics,const CFX_Matrix & mtMatrix)208 void CFWL_WidgetMgr::DrawChildren(CFWL_Widget* parent,
209                                   const CFX_RectF& rtClip,
210                                   CFGAS_GEGraphics* pGraphics,
211                                   const CFX_Matrix& mtMatrix) {
212   if (!parent)
213     return;
214 
215   CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
216   while (pNextChild) {
217     CFWL_Widget* child = pNextChild;
218     pNextChild = GetNextSiblingWidget(child);
219     if (!child->IsVisible())
220       continue;
221 
222     CFX_RectF rtWidget = child->GetWidgetRect();
223     if (rtWidget.IsEmpty())
224       continue;
225 
226     CFX_Matrix widgetMatrix;
227     CFX_RectF clipBounds(rtWidget);
228     widgetMatrix.Concat(mtMatrix);
229     widgetMatrix.TranslatePrepend(rtWidget.left, rtWidget.top);
230 
231     if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate())
232       pDelegate->OnDrawWidget(pGraphics, widgetMatrix);
233 
234     DrawChildren(child, clipBounds, pGraphics, widgetMatrix);
235   }
236 }
237 
Item(CFWL_Widget * widget)238 CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) : pWidget(widget) {}
239 
240 CFWL_WidgetMgr::Item::~Item() = default;
241 
Trace(cppgc::Visitor * visitor) const242 void CFWL_WidgetMgr::Item::Trace(cppgc::Visitor* visitor) const {
243   GCedTreeNode<Item>::Trace(visitor);
244   visitor->Trace(pWidget);
245 }
246 
247 }  // namespace pdfium
248