OLD | NEW |
| (Empty) |
1 // Copyright 2014 PDFium Authors. All rights reserved. | |
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/core/fwl_widgetmgrimp.h" | |
8 | |
9 #include "xfa/fwl/core/cfwl_message.h" | |
10 #include "xfa/fwl/core/fwl_appimp.h" | |
11 #include "xfa/fwl/core/fwl_noteimp.h" | |
12 #include "xfa/fwl/core/fwl_widgetimp.h" | |
13 #include "xfa/fwl/core/ifwl_app.h" | |
14 #include "xfa/fwl/core/ifwl_form.h" | |
15 #include "xfa/fxfa/app/xfa_fwladapter.h" | |
16 #include "xfa/fxfa/include/xfa_ffapp.h" | |
17 | |
18 namespace { | |
19 | |
20 const int kNeedRepaintHitPoints = 12; | |
21 const int kNeedRepaintHitPiece = 3; | |
22 | |
23 struct FWL_NEEDREPAINTHITDATA { | |
24 CFX_PointF hitPoint; | |
25 bool bNotNeedRepaint; | |
26 bool bNotContainByDirty; | |
27 }; | |
28 | |
29 } // namespace | |
30 | |
31 FX_BOOL FWL_UseOffscreen(IFWL_Widget* pWidget) { | |
32 #if (_FX_OS_ == _FX_MACOSX_) | |
33 return FALSE; | |
34 #else | |
35 return pWidget->GetStyles() & FWL_WGTSTYLE_Offscreen; | |
36 #endif | |
37 } | |
38 | |
39 // static | |
40 CFWL_WidgetMgr* CFWL_WidgetMgr::GetInstance() { | |
41 IFWL_App* pApp = FWL_GetApp(); | |
42 return pApp ? pApp->GetWidgetMgr() : nullptr; | |
43 } | |
44 | |
45 CFWL_WidgetMgr::CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative) | |
46 : m_dwCapability(0), | |
47 m_pDelegate(new CFWL_WidgetMgrDelegate(this)), | |
48 m_pAdapter(pAdapterNative->GetWidgetMgr(m_pDelegate.get())) { | |
49 ASSERT(m_pAdapter); | |
50 m_mapWidgetItem[nullptr].reset(new CFWL_WidgetMgrItem); | |
51 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
52 m_rtScreen.Reset(); | |
53 #endif | |
54 } | |
55 | |
56 CFWL_WidgetMgr::~CFWL_WidgetMgr() {} | |
57 | |
58 IFWL_Widget* CFWL_WidgetMgr::GetParentWidget(IFWL_Widget* pWidget) const { | |
59 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
60 return pItem && pItem->pParent ? pItem->pParent->pWidget : nullptr; | |
61 } | |
62 | |
63 IFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(IFWL_Widget* pWidget) const { | |
64 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
65 return pItem && pItem->pOwner ? pItem->pOwner->pWidget : nullptr; | |
66 } | |
67 | |
68 IFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(IFWL_Widget* pWidget) const { | |
69 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
70 pItem = pItem ? pItem->pPrevious : nullptr; // Not self. | |
71 while (pItem && pItem->pPrevious) | |
72 pItem = pItem->pPrevious; | |
73 | |
74 return pItem ? pItem->pWidget : nullptr; | |
75 } | |
76 | |
77 IFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(IFWL_Widget* pWidget) const { | |
78 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
79 return pItem && pItem->pPrevious ? pItem->pPrevious->pWidget : nullptr; | |
80 } | |
81 | |
82 IFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(IFWL_Widget* pWidget) const { | |
83 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
84 return pItem && pItem->pNext ? pItem->pNext->pWidget : nullptr; | |
85 } | |
86 | |
87 IFWL_Widget* CFWL_WidgetMgr::GetLastSiblingWidget(IFWL_Widget* pWidget) const { | |
88 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
89 pItem = pItem ? pItem->pNext : nullptr; // Not self. | |
90 while (pItem && pItem->pNext) | |
91 pItem = pItem->pNext; | |
92 | |
93 return pItem ? pItem->pWidget : nullptr; | |
94 } | |
95 | |
96 IFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(IFWL_Widget* pWidget) const { | |
97 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
98 return pItem && pItem->pChild ? pItem->pChild->pWidget : nullptr; | |
99 } | |
100 | |
101 IFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(IFWL_Widget* pWidget) const { | |
102 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
103 pItem = pItem ? pItem->pChild : nullptr; | |
104 while (pItem && pItem->pNext) | |
105 pItem = pItem->pNext; | |
106 | |
107 return pItem ? pItem->pWidget : nullptr; | |
108 } | |
109 | |
110 IFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(IFWL_Widget* pWidget) const { | |
111 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
112 while (pItem) { | |
113 if (IsAbleNative(pItem->pWidget)) | |
114 return pItem->pWidget; | |
115 pItem = pItem->pParent; | |
116 } | |
117 return nullptr; | |
118 } | |
119 | |
120 FX_BOOL CFWL_WidgetMgr::SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex) { | |
121 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
122 if (!pItem) | |
123 return FALSE; | |
124 if (!pItem->pParent) | |
125 return FALSE; | |
126 CFWL_WidgetMgrItem* pChild = pItem->pParent->pChild; | |
127 int32_t i = 0; | |
128 while (pChild) { | |
129 if (pChild == pItem) { | |
130 if (i == nIndex) { | |
131 return TRUE; | |
132 } | |
133 if (pChild->pPrevious) { | |
134 pChild->pPrevious->pNext = pChild->pNext; | |
135 } | |
136 if (pChild->pNext) { | |
137 pChild->pNext->pPrevious = pChild->pPrevious; | |
138 } | |
139 if (pItem->pParent->pChild == pItem) { | |
140 pItem->pParent->pChild = pItem->pNext; | |
141 } | |
142 pItem->pNext = NULL; | |
143 pItem->pPrevious = NULL; | |
144 break; | |
145 } | |
146 if (!pChild->pNext) { | |
147 break; | |
148 } | |
149 pChild = pChild->pNext; | |
150 ++i; | |
151 } | |
152 pChild = pItem->pParent->pChild; | |
153 if (pChild) { | |
154 if (nIndex < 0) { | |
155 while (pChild->pNext) { | |
156 pChild = pChild->pNext; | |
157 } | |
158 pChild->pNext = pItem; | |
159 pItem->pPrevious = pChild; | |
160 pItem->pNext = NULL; | |
161 return TRUE; | |
162 } | |
163 i = 0; | |
164 while (i < nIndex && pChild->pNext) { | |
165 pChild = pChild->pNext; | |
166 ++i; | |
167 } | |
168 if (!pChild->pNext) { | |
169 pChild->pNext = pItem; | |
170 pItem->pPrevious = pChild; | |
171 pItem->pNext = NULL; | |
172 return TRUE; | |
173 } | |
174 if (pChild->pPrevious) { | |
175 pItem->pPrevious = pChild->pPrevious; | |
176 pChild->pPrevious->pNext = pItem; | |
177 } | |
178 pChild->pPrevious = pItem; | |
179 pItem->pNext = pChild; | |
180 if (pItem->pParent->pChild == pChild) { | |
181 pItem->pParent->pChild = pItem; | |
182 } | |
183 } else { | |
184 pItem->pParent->pChild = pItem; | |
185 pItem->pPrevious = NULL; | |
186 pItem->pNext = NULL; | |
187 } | |
188 return TRUE; | |
189 } | |
190 FWL_Error CFWL_WidgetMgr::RepaintWidget(IFWL_Widget* pWidget, | |
191 const CFX_RectF* pRect) { | |
192 if (!m_pAdapter) | |
193 return FWL_Error::Indefinite; | |
194 IFWL_Widget* pNative = pWidget; | |
195 CFX_RectF rect(*pRect); | |
196 if (IsFormDisabled()) { | |
197 IFWL_Widget* pOuter = pWidget->GetOuter(); | |
198 while (pOuter) { | |
199 CFX_RectF rtTemp; | |
200 pNative->GetWidgetRect(rtTemp); | |
201 rect.left += rtTemp.left; | |
202 rect.top += rtTemp.top; | |
203 pNative = pOuter; | |
204 pOuter = pOuter->GetOuter(); | |
205 } | |
206 } else if (!IsAbleNative(pWidget)) { | |
207 pNative = GetSystemFormWidget(pWidget); | |
208 if (!pNative) | |
209 return FWL_Error::Indefinite; | |
210 pWidget->TransformTo(pNative, rect.left, rect.top); | |
211 } | |
212 AddRedrawCounts(pNative); | |
213 return m_pAdapter->RepaintWidget(pNative, &rect); | |
214 } | |
215 void CFWL_WidgetMgr::AddWidget(IFWL_Widget* pWidget) { | |
216 CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(NULL); | |
217 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
218 if (!pItem) { | |
219 pItem = new CFWL_WidgetMgrItem(pWidget); | |
220 m_mapWidgetItem[pWidget].reset(pItem); | |
221 } | |
222 if (pItem->pParent && pItem->pParent != pParentItem) { | |
223 if (pItem->pPrevious) { | |
224 pItem->pPrevious->pNext = pItem->pNext; | |
225 } | |
226 if (pItem->pNext) { | |
227 pItem->pNext->pPrevious = pItem->pPrevious; | |
228 } | |
229 if (pItem->pParent->pChild == pItem) { | |
230 pItem->pParent->pChild = pItem->pNext; | |
231 } | |
232 } | |
233 pItem->pParent = pParentItem; | |
234 SetWidgetIndex(pWidget, -1); | |
235 } | |
236 void CFWL_WidgetMgr::InsertWidget(IFWL_Widget* pParent, | |
237 IFWL_Widget* pChild, | |
238 int32_t nIndex) { | |
239 CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
240 if (!pParentItem) { | |
241 pParentItem = new CFWL_WidgetMgrItem(pParent); | |
242 m_mapWidgetItem[pParent].reset(pParentItem); | |
243 pParentItem->pParent = GetWidgetMgrItem(nullptr); | |
244 SetWidgetIndex(pParent, -1); | |
245 } | |
246 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pChild); | |
247 if (!pItem) { | |
248 pItem = new CFWL_WidgetMgrItem(pChild); | |
249 m_mapWidgetItem[pChild].reset(pItem); | |
250 } | |
251 if (pItem->pParent && pItem->pParent != pParentItem) { | |
252 if (pItem->pPrevious) { | |
253 pItem->pPrevious->pNext = pItem->pNext; | |
254 } | |
255 if (pItem->pNext) { | |
256 pItem->pNext->pPrevious = pItem->pPrevious; | |
257 } | |
258 if (pItem->pParent->pChild == pItem) { | |
259 pItem->pParent->pChild = pItem->pNext; | |
260 } | |
261 } | |
262 pItem->pParent = pParentItem; | |
263 SetWidgetIndex(pChild, nIndex); | |
264 } | |
265 void CFWL_WidgetMgr::RemoveWidget(IFWL_Widget* pWidget) { | |
266 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
267 if (!pItem) { | |
268 return; | |
269 } | |
270 if (pItem->pPrevious) { | |
271 pItem->pPrevious->pNext = pItem->pNext; | |
272 } | |
273 if (pItem->pNext) { | |
274 pItem->pNext->pPrevious = pItem->pPrevious; | |
275 } | |
276 if (pItem->pParent && pItem->pParent->pChild == pItem) { | |
277 pItem->pParent->pChild = pItem->pNext; | |
278 } | |
279 CFWL_WidgetMgrItem* pChild = pItem->pChild; | |
280 while (pChild) { | |
281 CFWL_WidgetMgrItem* pNext = pChild->pNext; | |
282 RemoveWidget(pChild->pWidget); | |
283 pChild = pNext; | |
284 } | |
285 m_mapWidgetItem.erase(pWidget); | |
286 } | |
287 void CFWL_WidgetMgr::SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned) { | |
288 CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pOwner); | |
289 if (!pParentItem) { | |
290 pParentItem = new CFWL_WidgetMgrItem(pOwner); | |
291 m_mapWidgetItem[pOwner].reset(pParentItem); | |
292 pParentItem->pParent = GetWidgetMgrItem(nullptr); | |
293 SetWidgetIndex(pOwner, -1); | |
294 } | |
295 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pOwned); | |
296 if (!pItem) { | |
297 pItem = new CFWL_WidgetMgrItem(pOwned); | |
298 m_mapWidgetItem[pOwned].reset(pItem); | |
299 } | |
300 pItem->pOwner = pParentItem; | |
301 } | |
302 void CFWL_WidgetMgr::SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild) { | |
303 CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
304 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pChild); | |
305 if (!pItem) | |
306 return; | |
307 if (pItem->pParent && pItem->pParent != pParentItem) { | |
308 if (pItem->pPrevious) { | |
309 pItem->pPrevious->pNext = pItem->pNext; | |
310 } | |
311 if (pItem->pNext) { | |
312 pItem->pNext->pPrevious = pItem->pPrevious; | |
313 } | |
314 if (pItem->pParent->pChild == pItem) { | |
315 pItem->pParent->pChild = pItem->pNext; | |
316 } | |
317 pItem->pNext = NULL; | |
318 pItem->pPrevious = NULL; | |
319 } | |
320 pItem->pParent = pParentItem; | |
321 SetWidgetIndex(pChild, -1); | |
322 } | |
323 | |
324 FX_BOOL CFWL_WidgetMgr::IsChild(IFWL_Widget* pChild, IFWL_Widget* pParent) { | |
325 IFWL_Widget* pTemp = pChild; | |
326 do { | |
327 if (pTemp == pParent) | |
328 return TRUE; | |
329 pTemp = GetParentWidget(pTemp); | |
330 } while (pTemp); | |
331 return FALSE; | |
332 } | |
333 | |
334 FWL_Error CFWL_WidgetMgr::SetWidgetRect_Native(IFWL_Widget* pWidget, | |
335 const CFX_RectF& rect) { | |
336 if (FWL_UseOffscreen(pWidget)) { | |
337 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
338 pItem->iRedrawCounter++; | |
339 if (pItem->pOffscreen) { | |
340 CFX_RenderDevice* pDevice = pItem->pOffscreen->GetRenderDevice(); | |
341 if (pDevice && pDevice->GetBitmap()) { | |
342 CFX_DIBitmap* pBitmap = pDevice->GetBitmap(); | |
343 if (pBitmap->GetWidth() - rect.width > 1 || | |
344 pBitmap->GetHeight() - rect.height > 1) { | |
345 pItem->pOffscreen.reset(); | |
346 } | |
347 } | |
348 } | |
349 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
350 pItem->bOutsideChanged = !m_rtScreen.Contains(rect); | |
351 #endif | |
352 } | |
353 return FWL_Error::Succeeded; | |
354 } | |
355 | |
356 IFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(IFWL_Widget* parent, | |
357 FX_FLOAT x, | |
358 FX_FLOAT y) { | |
359 if (!parent) | |
360 return NULL; | |
361 FX_FLOAT x1; | |
362 FX_FLOAT y1; | |
363 IFWL_Widget* child = GetLastChildWidget(parent); | |
364 while (child) { | |
365 if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) { | |
366 x1 = x; | |
367 y1 = y; | |
368 CFX_Matrix matrixOnParent; | |
369 child->GetMatrix(matrixOnParent); | |
370 CFX_Matrix m; | |
371 m.SetIdentity(); | |
372 m.SetReverse(matrixOnParent); | |
373 m.TransformPoint(x1, y1); | |
374 CFX_RectF bounds; | |
375 child->GetWidgetRect(bounds); | |
376 if (bounds.Contains(x1, y1)) { | |
377 x1 -= bounds.left; | |
378 y1 -= bounds.top; | |
379 return GetWidgetAtPoint(child, x1, y1); | |
380 } | |
381 } | |
382 child = GetPriorSiblingWidget(child); | |
383 } | |
384 return parent; | |
385 } | |
386 | |
387 void CFWL_WidgetMgr::NotifySizeChanged(IFWL_Widget* pForm, | |
388 FX_FLOAT fx, | |
389 FX_FLOAT fy) { | |
390 if (FWL_UseOffscreen(pForm)) | |
391 GetWidgetMgrItem(pForm)->pOffscreen.reset(); | |
392 } | |
393 | |
394 IFWL_Widget* CFWL_WidgetMgr::nextTab(IFWL_Widget* parent, | |
395 IFWL_Widget* focus, | |
396 FX_BOOL& bFind) { | |
397 CFWL_WidgetMgr* pMgr = CFWL_WidgetMgr::GetInstance(); | |
398 IFWL_Widget* child = pMgr->GetFirstChildWidget(parent); | |
399 while (child) { | |
400 if (focus == child) | |
401 bFind = TRUE; | |
402 | |
403 if ((child->GetStyles() & FWL_WGTSTYLE_TabStop) && | |
404 (!focus || (focus != child && bFind))) { | |
405 return child; | |
406 } | |
407 IFWL_Widget* bRet = nextTab(child, focus, bFind); | |
408 if (bRet) | |
409 return bRet; | |
410 | |
411 child = pMgr->GetNextSiblingWidget(child); | |
412 } | |
413 return nullptr; | |
414 } | |
415 | |
416 int32_t CFWL_WidgetMgr::CountRadioButtonGroup(IFWL_Widget* pFirst) { | |
417 int32_t iRet = 0; | |
418 IFWL_Widget* pChild = pFirst; | |
419 while (pChild) { | |
420 pChild = GetNextSiblingWidget(pChild); | |
421 ++iRet; | |
422 } | |
423 return iRet; | |
424 } | |
425 IFWL_Widget* CFWL_WidgetMgr::GetSiblingRadioButton(IFWL_Widget* pWidget, | |
426 FX_BOOL bNext) { | |
427 return nullptr; | |
428 } | |
429 IFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader( | |
430 IFWL_Widget* pRadioButton) { | |
431 IFWL_Widget* pNext = pRadioButton; | |
432 while (pNext) { | |
433 if (pNext->GetStyles() & FWL_WGTSTYLE_Group) | |
434 return pNext; | |
435 pNext = GetSiblingRadioButton(pNext, FALSE); | |
436 } | |
437 pNext = GetLastSiblingWidget(pRadioButton); | |
438 while ((pNext = GetSiblingRadioButton(pNext, FALSE)) != nullptr && | |
439 pNext != pRadioButton) { | |
440 if (pNext->GetStyles() & FWL_WGTSTYLE_Group) | |
441 return pNext; | |
442 } | |
443 pNext = GetFirstSiblingWidget(pRadioButton); | |
444 return GetSiblingRadioButton(pNext, TRUE); | |
445 } | |
446 void CFWL_WidgetMgr::GetSameGroupRadioButton( | |
447 IFWL_Widget* pRadioButton, | |
448 CFX_ArrayTemplate<IFWL_Widget*>& group) { | |
449 IFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton); | |
450 if (!pFirst) { | |
451 pFirst = pRadioButton; | |
452 } | |
453 int32_t iGroup = CountRadioButtonGroup(pFirst); | |
454 if (iGroup < 2) { | |
455 IFWL_Widget* pNext = pFirst; | |
456 while ((pNext = GetSiblingRadioButton(pNext, TRUE)) != NULL) { | |
457 group.Add(pNext); | |
458 } | |
459 return; | |
460 } | |
461 IFWL_Widget* pNext = GetRadioButtonGroupHeader(pRadioButton); | |
462 do { | |
463 group.Add(pNext); | |
464 pNext = GetSiblingRadioButton(pNext, TRUE); | |
465 if (!pNext) | |
466 pNext = GetSiblingRadioButton(pFirst, TRUE); | |
467 } while (pNext && ((pNext->GetStyles() & FWL_WGTSTYLE_Group) == 0)); | |
468 } | |
469 IFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(IFWL_Widget* pParent) { | |
470 if ((pParent->GetClassID() == FWL_Type::PushButton) && | |
471 (pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { | |
472 return pParent; | |
473 } | |
474 IFWL_Widget* child = | |
475 CFWL_WidgetMgr::GetInstance()->GetFirstChildWidget(pParent); | |
476 while (child) { | |
477 if ((child->GetClassID() == FWL_Type::PushButton) && | |
478 (child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { | |
479 return child; | |
480 } | |
481 IFWL_Widget* find = GetDefaultButton(child); | |
482 if (find) { | |
483 return find; | |
484 } | |
485 child = CFWL_WidgetMgr::GetInstance()->GetNextSiblingWidget(child); | |
486 } | |
487 return NULL; | |
488 } | |
489 void CFWL_WidgetMgr::AddRedrawCounts(IFWL_Widget* pWidget) { | |
490 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
491 (pItem->iRedrawCounter)++; | |
492 } | |
493 void CFWL_WidgetMgr::ResetRedrawCounts(IFWL_Widget* pWidget) { | |
494 CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
495 pItem->iRedrawCounter = 0; | |
496 } | |
497 CFWL_WidgetMgrItem* CFWL_WidgetMgr::GetWidgetMgrItem( | |
498 IFWL_Widget* pWidget) const { | |
499 auto it = m_mapWidgetItem.find(pWidget); | |
500 return it != m_mapWidgetItem.end() | |
501 ? static_cast<CFWL_WidgetMgrItem*>(it->second.get()) | |
502 : nullptr; | |
503 } | |
504 int32_t CFWL_WidgetMgr::TravelWidgetMgr(CFWL_WidgetMgrItem* pParent, | |
505 int32_t* pIndex, | |
506 CFWL_WidgetMgrItem* pItem, | |
507 IFWL_Widget** pWidget) { | |
508 if (!pParent) { | |
509 return 0; | |
510 } | |
511 int32_t iCount = 0; | |
512 CFWL_WidgetMgrItem* pChild = pParent->pChild; | |
513 while (pChild) { | |
514 iCount++; | |
515 if (pIndex) { | |
516 if (*pIndex == 0) { | |
517 *pWidget = pChild->pWidget; | |
518 return iCount; | |
519 } | |
520 pIndex--; | |
521 } | |
522 if (pItem && pItem == pChild) { | |
523 return iCount - 1; | |
524 } | |
525 pChild = pChild->pNext; | |
526 } | |
527 if (pIndex) { | |
528 return 0; | |
529 } else if (pItem) { | |
530 return -1; | |
531 } | |
532 return iCount - 1; | |
533 } | |
534 | |
535 FX_BOOL CFWL_WidgetMgr::IsAbleNative(IFWL_Widget* pWidget) const { | |
536 if (!pWidget) | |
537 return FALSE; | |
538 if (!pWidget->IsInstance(FX_WSTRC(FWL_CLASS_Form))) { | |
539 return FALSE; | |
540 } | |
541 uint32_t dwStyles = pWidget->GetStyles(); | |
542 return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) == | |
543 FWL_WGTSTYLE_OverLapper) || | |
544 (dwStyles & FWL_WGTSTYLE_Popup); | |
545 } | |
546 | |
547 bool CFWL_WidgetMgr::IsThreadEnabled() { | |
548 return !(m_dwCapability & FWL_WGTMGR_DisableThread); | |
549 } | |
550 | |
551 bool CFWL_WidgetMgr::IsFormDisabled() { | |
552 return !!(m_dwCapability & FWL_WGTMGR_DisableForm); | |
553 } | |
554 | |
555 FX_BOOL CFWL_WidgetMgr::GetAdapterPopupPos(IFWL_Widget* pWidget, | |
556 FX_FLOAT fMinHeight, | |
557 FX_FLOAT fMaxHeight, | |
558 const CFX_RectF& rtAnchor, | |
559 CFX_RectF& rtPopup) { | |
560 CXFA_FWLAdapterWidgetMgr* pSDApapter = GetAdapterWidgetMgr(); | |
561 return pSDApapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, | |
562 rtPopup); | |
563 } | |
564 CFWL_WidgetMgrDelegate::CFWL_WidgetMgrDelegate(CFWL_WidgetMgr* pWidgetMgr) | |
565 : m_pWidgetMgr(pWidgetMgr) {} | |
566 FWL_Error CFWL_WidgetMgrDelegate::OnSetCapability(uint32_t dwCapability) { | |
567 m_pWidgetMgr->m_dwCapability = dwCapability; | |
568 return FWL_Error::Succeeded; | |
569 } | |
570 | |
571 void CFWL_WidgetMgrDelegate::OnProcessMessageToForm(CFWL_Message* pMessage) { | |
572 if (!pMessage) | |
573 return; | |
574 if (!pMessage->m_pDstTarget) | |
575 return; | |
576 | |
577 IFWL_Widget* pDstWidget = pMessage->m_pDstTarget; | |
578 IFWL_App* pApp = pDstWidget->GetOwnerApp(); | |
579 if (!pApp) | |
580 return; | |
581 | |
582 CFWL_NoteDriver* pNoteDriver = | |
583 static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); | |
584 if (!pNoteDriver) | |
585 return; | |
586 | |
587 if (m_pWidgetMgr->IsThreadEnabled()) | |
588 pMessage = static_cast<CFWL_Message*>(pMessage->Clone()); | |
589 if (m_pWidgetMgr->IsFormDisabled()) | |
590 pNoteDriver->ProcessMessage(pMessage); | |
591 else | |
592 pNoteDriver->QueueMessage(pMessage); | |
593 | |
594 #if (_FX_OS_ == _FX_MACOSX_) | |
595 CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop(); | |
596 if (pTopLoop) | |
597 pNoteDriver->UnqueueMessage(pTopLoop); | |
598 #endif | |
599 | |
600 if (m_pWidgetMgr->IsThreadEnabled()) | |
601 pMessage->Release(); | |
602 | |
603 return; | |
604 } | |
605 | |
606 void CFWL_WidgetMgrDelegate::OnDrawWidget(IFWL_Widget* pWidget, | |
607 CFX_Graphics* pGraphics, | |
608 const CFX_Matrix* pMatrix) { | |
609 if (!pWidget || !pGraphics) | |
610 return; | |
611 | |
612 CFX_Graphics* pTemp = DrawWidgetBefore(pWidget, pGraphics, pMatrix); | |
613 CFX_RectF clipCopy; | |
614 pWidget->GetWidgetRect(clipCopy); | |
615 clipCopy.left = clipCopy.top = 0; | |
616 if (bUseOffscreenDirect(pWidget)) { | |
617 DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix); | |
618 return; | |
619 } | |
620 CFX_RectF clipBounds; | |
621 | |
622 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) || \ | |
623 (_FX_OS_ == _FX_LINUX_DESKTOP_) || (_FX_OS_ == _FX_ANDROID_) | |
624 IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
625 pDelegate->OnDrawWidget(pTemp, pMatrix); | |
626 pGraphics->GetClipRect(clipBounds); | |
627 clipCopy = clipBounds; | |
628 #elif(_FX_OS_ == _FX_MACOSX_) | |
629 if (m_pWidgetMgr->IsFormDisabled()) { | |
630 IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
631 pDelegate->OnDrawWidget(pTemp, pMatrix); | |
632 pGraphics->GetClipRect(clipBounds); | |
633 clipCopy = clipBounds; | |
634 } else { | |
635 clipBounds.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d); | |
636 const_cast<CFX_Matrix*>(pMatrix)->SetIdentity(); // FIXME: const cast. | |
637 IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
638 pDelegate->OnDrawWidget(pTemp, pMatrix); | |
639 } | |
640 #endif // _FX_OS_ == _FX_MACOSX_ | |
641 | |
642 if (!m_pWidgetMgr->IsFormDisabled()) { | |
643 CFX_RectF rtClient; | |
644 pWidget->GetClientRect(rtClient); | |
645 clipBounds.Intersect(rtClient); | |
646 } | |
647 if (!clipBounds.IsEmpty()) | |
648 DrawChild(pWidget, clipBounds, pTemp, pMatrix); | |
649 | |
650 DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix); | |
651 m_pWidgetMgr->ResetRedrawCounts(pWidget); | |
652 } | |
653 | |
654 void CFWL_WidgetMgrDelegate::DrawChild(IFWL_Widget* parent, | |
655 const CFX_RectF& rtClip, | |
656 CFX_Graphics* pGraphics, | |
657 const CFX_Matrix* pMatrix) { | |
658 if (!parent) | |
659 return; | |
660 | |
661 FX_BOOL bFormDisable = m_pWidgetMgr->IsFormDisabled(); | |
662 IFWL_Widget* pNextChild = m_pWidgetMgr->GetFirstChildWidget(parent); | |
663 while (pNextChild) { | |
664 IFWL_Widget* child = pNextChild; | |
665 pNextChild = m_pWidgetMgr->GetNextSiblingWidget(child); | |
666 if (child->GetStates() & FWL_WGTSTATE_Invisible) | |
667 continue; | |
668 | |
669 CFX_RectF rtWidget; | |
670 child->GetWidgetRect(rtWidget); | |
671 if (rtWidget.IsEmpty()) | |
672 continue; | |
673 | |
674 CFX_Matrix widgetMatrix; | |
675 CFX_RectF clipBounds(rtWidget); | |
676 if (!bFormDisable) | |
677 child->GetMatrix(widgetMatrix, TRUE); | |
678 if (pMatrix) | |
679 widgetMatrix.Concat(*pMatrix); | |
680 | |
681 if (!bFormDisable) { | |
682 widgetMatrix.TransformPoint(clipBounds.left, clipBounds.top); | |
683 clipBounds.Intersect(rtClip); | |
684 if (clipBounds.IsEmpty()) | |
685 continue; | |
686 | |
687 pGraphics->SaveGraphState(); | |
688 pGraphics->SetClipRect(clipBounds); | |
689 } | |
690 widgetMatrix.Translate(rtWidget.left, rtWidget.top, TRUE); | |
691 IFWL_WidgetDelegate* pDelegate = child->SetDelegate(NULL); | |
692 if (pDelegate) { | |
693 if (m_pWidgetMgr->IsFormDisabled() || | |
694 IsNeedRepaint(child, &widgetMatrix, rtClip)) { | |
695 pDelegate->OnDrawWidget(pGraphics, &widgetMatrix); | |
696 } | |
697 } | |
698 if (!bFormDisable) | |
699 pGraphics->RestoreGraphState(); | |
700 | |
701 DrawChild(child, clipBounds, pGraphics, | |
702 bFormDisable ? &widgetMatrix : pMatrix); | |
703 child = m_pWidgetMgr->GetNextSiblingWidget(child); | |
704 } | |
705 } | |
706 | |
707 CFX_Graphics* CFWL_WidgetMgrDelegate::DrawWidgetBefore( | |
708 IFWL_Widget* pWidget, | |
709 CFX_Graphics* pGraphics, | |
710 const CFX_Matrix* pMatrix) { | |
711 if (!FWL_UseOffscreen(pWidget)) | |
712 return pGraphics; | |
713 | |
714 CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
715 if (!pItem->pOffscreen) { | |
716 pItem->pOffscreen.reset(new CFX_Graphics); | |
717 CFX_RectF rect; | |
718 pWidget->GetWidgetRect(rect); | |
719 pItem->pOffscreen->Create((int32_t)rect.width, (int32_t)rect.height, | |
720 FXDIB_Argb); | |
721 } | |
722 CFX_RectF rect; | |
723 pGraphics->GetClipRect(rect); | |
724 pItem->pOffscreen->SetClipRect(rect); | |
725 return pItem->pOffscreen.get(); | |
726 } | |
727 | |
728 void CFWL_WidgetMgrDelegate::DrawWidgetAfter(IFWL_Widget* pWidget, | |
729 CFX_Graphics* pGraphics, | |
730 CFX_RectF& rtClip, | |
731 const CFX_Matrix* pMatrix) { | |
732 if (FWL_UseOffscreen(pWidget)) { | |
733 CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
734 pGraphics->Transfer(pItem->pOffscreen.get(), rtClip.left, rtClip.top, | |
735 rtClip, pMatrix); | |
736 #ifdef _WIN32 | |
737 pItem->pOffscreen->ClearClip(); | |
738 #endif | |
739 } | |
740 CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
741 pItem->iRedrawCounter = 0; | |
742 } | |
743 | |
744 FX_BOOL CFWL_WidgetMgrDelegate::IsNeedRepaint(IFWL_Widget* pWidget, | |
745 CFX_Matrix* pMatrix, | |
746 const CFX_RectF& rtDirty) { | |
747 CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
748 if (pItem && pItem->iRedrawCounter > 0) { | |
749 pItem->iRedrawCounter = 0; | |
750 return TRUE; | |
751 } | |
752 CFX_RectF rtWidget; | |
753 pWidget->GetWidgetRect(rtWidget); | |
754 rtWidget.left = rtWidget.top = 0; | |
755 pMatrix->TransformRect(rtWidget); | |
756 if (!rtWidget.IntersectWith(rtDirty)) | |
757 return FALSE; | |
758 | |
759 IFWL_Widget* pChild = | |
760 CFWL_WidgetMgr::GetInstance()->GetFirstChildWidget(pWidget); | |
761 if (!pChild) | |
762 return TRUE; | |
763 | |
764 CFX_RectF rtChilds; | |
765 rtChilds.Empty(); | |
766 FX_BOOL bChildIntersectWithDirty = FALSE; | |
767 FX_BOOL bOrginPtIntersectWidthChild = FALSE; | |
768 FX_BOOL bOrginPtIntersectWidthDirty = | |
769 rtDirty.Contains(rtWidget.left, rtWidget.top); | |
770 static FWL_NEEDREPAINTHITDATA hitPoint[kNeedRepaintHitPoints]; | |
771 int32_t iSize = sizeof(FWL_NEEDREPAINTHITDATA); | |
772 FXSYS_memset(hitPoint, 0, iSize); | |
773 FX_FLOAT fxPiece = rtWidget.width / kNeedRepaintHitPiece; | |
774 FX_FLOAT fyPiece = rtWidget.height / kNeedRepaintHitPiece; | |
775 hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left; | |
776 hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x = | |
777 hitPoint[10].hitPoint.x = fxPiece + rtWidget.left; | |
778 hitPoint[1].hitPoint.x = hitPoint[4].hitPoint.x = hitPoint[8].hitPoint.x = | |
779 hitPoint[11].hitPoint.x = fxPiece * 2 + rtWidget.left; | |
780 hitPoint[5].hitPoint.x = hitPoint[9].hitPoint.x = | |
781 rtWidget.width + rtWidget.left; | |
782 hitPoint[0].hitPoint.y = hitPoint[1].hitPoint.y = rtWidget.top; | |
783 hitPoint[2].hitPoint.y = hitPoint[3].hitPoint.y = hitPoint[4].hitPoint.y = | |
784 hitPoint[5].hitPoint.y = fyPiece + rtWidget.top; | |
785 hitPoint[6].hitPoint.y = hitPoint[7].hitPoint.y = hitPoint[8].hitPoint.y = | |
786 hitPoint[9].hitPoint.y = fyPiece * 2 + rtWidget.top; | |
787 hitPoint[10].hitPoint.y = hitPoint[11].hitPoint.y = | |
788 rtWidget.height + rtWidget.top; | |
789 do { | |
790 CFX_RectF rect; | |
791 pChild->GetWidgetRect(rect); | |
792 CFX_RectF r = rect; | |
793 r.left += rtWidget.left; | |
794 r.top += rtWidget.top; | |
795 if (r.IsEmpty()) | |
796 continue; | |
797 if (r.Contains(rtDirty)) | |
798 return FALSE; | |
799 if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty)) | |
800 bChildIntersectWithDirty = TRUE; | |
801 if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) | |
802 bOrginPtIntersectWidthChild = rect.Contains(0, 0); | |
803 | |
804 if (rtChilds.IsEmpty()) | |
805 rtChilds = rect; | |
806 else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible)) | |
807 rtChilds.Union(rect); | |
808 | |
809 for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) { | |
810 if (hitPoint[i].bNotContainByDirty || hitPoint[i].bNotNeedRepaint) | |
811 continue; | |
812 if (!rtDirty.Contains(hitPoint[i].hitPoint)) { | |
813 hitPoint[i].bNotContainByDirty = true; | |
814 continue; | |
815 } | |
816 if (r.Contains(hitPoint[i].hitPoint)) | |
817 hitPoint[i].bNotNeedRepaint = true; | |
818 } | |
819 } while ( | |
820 (pChild = CFWL_WidgetMgr::GetInstance()->GetNextSiblingWidget(pChild))); | |
821 | |
822 if (!bChildIntersectWithDirty) | |
823 return TRUE; | |
824 if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) | |
825 return TRUE; | |
826 if (rtChilds.IsEmpty()) | |
827 return TRUE; | |
828 | |
829 int32_t repaintPoint = kNeedRepaintHitPoints; | |
830 for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) { | |
831 if (hitPoint[i].bNotNeedRepaint) | |
832 repaintPoint--; | |
833 } | |
834 if (repaintPoint > 0) | |
835 return TRUE; | |
836 | |
837 pMatrix->TransformRect(rtChilds); | |
838 if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget)) | |
839 return FALSE; | |
840 return TRUE; | |
841 } | |
842 | |
843 FX_BOOL CFWL_WidgetMgrDelegate::bUseOffscreenDirect(IFWL_Widget* pWidget) { | |
844 CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
845 if (!FWL_UseOffscreen(pWidget) || !(pItem->pOffscreen)) | |
846 return FALSE; | |
847 | |
848 #if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
849 if (pItem->bOutsideChanged) { | |
850 CFX_RectF r; | |
851 pWidget->GetWidgetRect(r); | |
852 CFX_RectF temp(m_pWidgetMgr->m_rtScreen); | |
853 temp.Deflate(50, 50); | |
854 if (!temp.Contains(r)) | |
855 return FALSE; | |
856 | |
857 pItem->bOutsideChanged = FALSE; | |
858 } | |
859 #endif | |
860 | |
861 return pItem->iRedrawCounter == 0; | |
862 } | |
OLD | NEW |