| 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 |