You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
622 lines
18 KiB
622 lines
18 KiB
// Copyright 2014 PDFium Authors. All rights reserved. |
|
// Use of this source code is governed by a BSD-style license that can be |
|
// found in the LICENSE file. |
|
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
|
|
|
#include "xfa/fwl/cfwl_widgetmgr.h" |
|
|
|
#include <utility> |
|
|
|
#include "third_party/base/ptr_util.h" |
|
#include "xfa/fwl/cfwl_app.h" |
|
#include "xfa/fwl/cfwl_form.h" |
|
#include "xfa/fwl/cfwl_notedriver.h" |
|
#include "xfa/fxfa/app/xfa_fwladapter.h" |
|
#include "xfa/fxfa/xfa_ffapp.h" |
|
|
|
namespace { |
|
|
|
const int kNeedRepaintHitPoints = 12; |
|
const int kNeedRepaintHitPiece = 3; |
|
|
|
struct FWL_NEEDREPAINTHITDATA { |
|
CFX_PointF hitPoint; |
|
bool bNotNeedRepaint; |
|
bool bNotContainByDirty; |
|
}; |
|
|
|
} // namespace |
|
|
|
CFWL_WidgetMgr::CFWL_WidgetMgr(CXFA_FFApp* pAdapterNative) |
|
: m_dwCapability(0), m_pAdapter(pAdapterNative->GetWidgetMgr(this)) { |
|
ASSERT(m_pAdapter); |
|
m_mapWidgetItem[nullptr] = pdfium::MakeUnique<Item>(); |
|
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) |
|
m_rtScreen.Reset(); |
|
#endif |
|
} |
|
|
|
CFWL_WidgetMgr::~CFWL_WidgetMgr() {} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
return pItem && pItem->pParent ? pItem->pParent->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetOwnerWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
return pItem && pItem->pOwner ? pItem->pOwner->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetFirstSiblingWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
if (!pItem) |
|
return nullptr; |
|
|
|
pItem = pItem->pPrevious; |
|
while (pItem && pItem->pPrevious) |
|
pItem = pItem->pPrevious; |
|
return pItem ? pItem->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
return pItem && pItem->pPrevious ? pItem->pPrevious->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
return pItem && pItem->pNext ? pItem->pNext->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
return pItem && pItem->pChild ? pItem->pChild->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
if (!pItem) |
|
return nullptr; |
|
|
|
pItem = pItem->pChild; |
|
while (pItem && pItem->pNext) |
|
pItem = pItem->pNext; |
|
return pItem ? pItem->pWidget : nullptr; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetSystemFormWidget(CFWL_Widget* pWidget) const { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
while (pItem) { |
|
if (IsAbleNative(pItem->pWidget)) |
|
return pItem->pWidget; |
|
pItem = pItem->pParent; |
|
} |
|
return nullptr; |
|
} |
|
|
|
void CFWL_WidgetMgr::AppendWidget(CFWL_Widget* pWidget) { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
if (!pItem) |
|
return; |
|
if (!pItem->pParent) |
|
return; |
|
|
|
Item* pChild = pItem->pParent->pChild; |
|
int32_t i = 0; |
|
while (pChild) { |
|
if (pChild == pItem) { |
|
if (pChild->pPrevious) |
|
pChild->pPrevious->pNext = pChild->pNext; |
|
if (pChild->pNext) |
|
pChild->pNext->pPrevious = pChild->pPrevious; |
|
if (pItem->pParent->pChild == pItem) |
|
pItem->pParent->pChild = pItem->pNext; |
|
|
|
pItem->pNext = nullptr; |
|
pItem->pPrevious = nullptr; |
|
break; |
|
} |
|
if (!pChild->pNext) |
|
break; |
|
|
|
pChild = pChild->pNext; |
|
++i; |
|
} |
|
|
|
pChild = pItem->pParent->pChild; |
|
if (pChild) { |
|
while (pChild->pNext) |
|
pChild = pChild->pNext; |
|
|
|
pChild->pNext = pItem; |
|
pItem->pPrevious = pChild; |
|
} else { |
|
pItem->pParent->pChild = pItem; |
|
pItem->pPrevious = nullptr; |
|
} |
|
pItem->pNext = nullptr; |
|
} |
|
|
|
void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget, |
|
const CFX_RectF& rect) { |
|
if (!m_pAdapter) |
|
return; |
|
|
|
CFWL_Widget* pNative = pWidget; |
|
CFX_RectF transformedRect = rect; |
|
if (IsFormDisabled()) { |
|
CFWL_Widget* pOuter = pWidget->GetOuter(); |
|
while (pOuter) { |
|
CFX_RectF rtTemp = pNative->GetWidgetRect(); |
|
transformedRect.left += rtTemp.left; |
|
transformedRect.top += rtTemp.top; |
|
pNative = pOuter; |
|
pOuter = pOuter->GetOuter(); |
|
} |
|
} else if (!IsAbleNative(pWidget)) { |
|
pNative = GetSystemFormWidget(pWidget); |
|
if (!pNative) |
|
return; |
|
|
|
CFX_PointF pos = pWidget->TransformTo( |
|
pNative, CFX_PointF(transformedRect.left, transformedRect.top)); |
|
transformedRect.left = pos.x; |
|
transformedRect.top = pos.y; |
|
} |
|
AddRedrawCounts(pNative); |
|
m_pAdapter->RepaintWidget(pNative); |
|
} |
|
|
|
void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) { |
|
Item* pParentItem = GetWidgetMgrItem(pParent); |
|
if (!pParentItem) { |
|
auto item = pdfium::MakeUnique<Item>(pParent); |
|
pParentItem = item.get(); |
|
m_mapWidgetItem[pParent] = std::move(item); |
|
|
|
pParentItem->pParent = GetWidgetMgrItem(nullptr); |
|
AppendWidget(pParent); |
|
} |
|
|
|
Item* pItem = GetWidgetMgrItem(pChild); |
|
if (!pItem) { |
|
auto item = pdfium::MakeUnique<Item>(pChild); |
|
pItem = item.get(); |
|
m_mapWidgetItem[pChild] = std::move(item); |
|
} |
|
if (pItem->pParent && pItem->pParent != pParentItem) { |
|
if (pItem->pPrevious) |
|
pItem->pPrevious->pNext = pItem->pNext; |
|
if (pItem->pNext) |
|
pItem->pNext->pPrevious = pItem->pPrevious; |
|
if (pItem->pParent->pChild == pItem) |
|
pItem->pParent->pChild = pItem->pNext; |
|
} |
|
pItem->pParent = pParentItem; |
|
AppendWidget(pChild); |
|
} |
|
|
|
void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
if (!pItem) |
|
return; |
|
if (pItem->pPrevious) |
|
pItem->pPrevious->pNext = pItem->pNext; |
|
if (pItem->pNext) |
|
pItem->pNext->pPrevious = pItem->pPrevious; |
|
if (pItem->pParent && pItem->pParent->pChild == pItem) |
|
pItem->pParent->pChild = pItem->pNext; |
|
|
|
Item* pChild = pItem->pChild; |
|
while (pChild) { |
|
Item* pNext = pChild->pNext; |
|
RemoveWidget(pChild->pWidget); |
|
pChild = pNext; |
|
} |
|
m_mapWidgetItem.erase(pWidget); |
|
} |
|
|
|
void CFWL_WidgetMgr::SetOwner(CFWL_Widget* pOwner, CFWL_Widget* pOwned) { |
|
Item* pParentItem = GetWidgetMgrItem(pOwner); |
|
if (!pParentItem) { |
|
auto item = pdfium::MakeUnique<Item>(pOwner); |
|
pParentItem = item.get(); |
|
m_mapWidgetItem[pOwner] = std::move(item); |
|
|
|
pParentItem->pParent = GetWidgetMgrItem(nullptr); |
|
AppendWidget(pOwner); |
|
} |
|
|
|
Item* pItem = GetWidgetMgrItem(pOwned); |
|
if (!pItem) { |
|
auto item = pdfium::MakeUnique<Item>(pOwned); |
|
pItem = item.get(); |
|
m_mapWidgetItem[pOwned] = std::move(item); |
|
} |
|
pItem->pOwner = pParentItem; |
|
} |
|
void CFWL_WidgetMgr::SetParent(CFWL_Widget* pParent, CFWL_Widget* pChild) { |
|
Item* pParentItem = GetWidgetMgrItem(pParent); |
|
Item* pItem = GetWidgetMgrItem(pChild); |
|
if (!pItem) |
|
return; |
|
if (pItem->pParent && pItem->pParent != pParentItem) { |
|
if (pItem->pPrevious) |
|
pItem->pPrevious->pNext = pItem->pNext; |
|
if (pItem->pNext) |
|
pItem->pNext->pPrevious = pItem->pPrevious; |
|
if (pItem->pParent->pChild == pItem) |
|
pItem->pParent->pChild = pItem->pNext; |
|
|
|
pItem->pNext = nullptr; |
|
pItem->pPrevious = nullptr; |
|
} |
|
pItem->pParent = pParentItem; |
|
AppendWidget(pChild); |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent, |
|
const CFX_PointF& point) const { |
|
if (!parent) |
|
return nullptr; |
|
|
|
CFX_PointF pos; |
|
CFWL_Widget* child = GetLastChildWidget(parent); |
|
while (child) { |
|
if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) { |
|
CFX_Matrix m; |
|
m.SetIdentity(); |
|
|
|
CFX_Matrix matrixOnParent; |
|
m.SetReverse(matrixOnParent); |
|
pos = m.Transform(point); |
|
|
|
CFX_RectF bounds = child->GetWidgetRect(); |
|
if (bounds.Contains(pos)) { |
|
pos -= bounds.TopLeft(); |
|
return GetWidgetAtPoint(child, pos); |
|
} |
|
} |
|
child = GetPriorSiblingWidget(child); |
|
} |
|
return parent; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::NextTab(CFWL_Widget* parent, |
|
CFWL_Widget* focus, |
|
bool& bFind) { |
|
CFWL_WidgetMgr* pMgr = parent->GetOwnerApp()->GetWidgetMgr(); |
|
CFWL_Widget* child = pMgr->GetFirstChildWidget(parent); |
|
while (child) { |
|
if (focus == child) |
|
bFind = true; |
|
|
|
CFWL_Widget* bRet = NextTab(child, focus, bFind); |
|
if (bRet) |
|
return bRet; |
|
|
|
child = pMgr->GetNextSiblingWidget(child); |
|
} |
|
return nullptr; |
|
} |
|
|
|
int32_t CFWL_WidgetMgr::CountRadioButtonGroup(CFWL_Widget* pFirst) const { |
|
int32_t iRet = 0; |
|
CFWL_Widget* pChild = pFirst; |
|
while (pChild) { |
|
pChild = GetNextSiblingWidget(pChild); |
|
++iRet; |
|
} |
|
return iRet; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader( |
|
CFWL_Widget* pRadioButton) const { |
|
CFWL_Widget* pNext = pRadioButton; |
|
if (pNext && (pNext->GetStyles() & FWL_WGTSTYLE_Group)) |
|
return pNext; |
|
return nullptr; |
|
} |
|
|
|
std::vector<CFWL_Widget*> CFWL_WidgetMgr::GetSameGroupRadioButton( |
|
CFWL_Widget* pRadioButton) const { |
|
CFWL_Widget* pFirst = GetFirstSiblingWidget(pRadioButton); |
|
if (!pFirst) |
|
pFirst = pRadioButton; |
|
|
|
if (CountRadioButtonGroup(pFirst) < 2) |
|
return std::vector<CFWL_Widget*>(); |
|
|
|
std::vector<CFWL_Widget*> group; |
|
group.push_back(GetRadioButtonGroupHeader(pRadioButton)); |
|
return group; |
|
} |
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(CFWL_Widget* pParent) const { |
|
if ((pParent->GetClassID() == FWL_Type::PushButton) && |
|
(pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { |
|
return pParent; |
|
} |
|
|
|
CFWL_Widget* child = |
|
pParent->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pParent); |
|
while (child) { |
|
if ((child->GetClassID() == FWL_Type::PushButton) && |
|
(child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { |
|
return child; |
|
} |
|
if (CFWL_Widget* find = GetDefaultButton(child)) |
|
return find; |
|
|
|
child = child->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(child); |
|
} |
|
return nullptr; |
|
} |
|
|
|
void CFWL_WidgetMgr::AddRedrawCounts(CFWL_Widget* pWidget) { |
|
GetWidgetMgrItem(pWidget)->iRedrawCounter++; |
|
} |
|
|
|
void CFWL_WidgetMgr::ResetRedrawCounts(CFWL_Widget* pWidget) { |
|
GetWidgetMgrItem(pWidget)->iRedrawCounter = 0; |
|
} |
|
|
|
CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem( |
|
CFWL_Widget* pWidget) const { |
|
auto it = m_mapWidgetItem.find(pWidget); |
|
return it != m_mapWidgetItem.end() ? static_cast<Item*>(it->second.get()) |
|
: nullptr; |
|
} |
|
|
|
bool CFWL_WidgetMgr::IsAbleNative(CFWL_Widget* pWidget) const { |
|
if (!pWidget) |
|
return false; |
|
if (!pWidget->IsInstance(FWL_CLASS_Form)) |
|
return false; |
|
|
|
uint32_t dwStyles = pWidget->GetStyles(); |
|
return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) == |
|
FWL_WGTSTYLE_OverLapper) || |
|
(dwStyles & FWL_WGTSTYLE_Popup); |
|
} |
|
|
|
void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget, |
|
FX_FLOAT fMinHeight, |
|
FX_FLOAT fMaxHeight, |
|
const CFX_RectF& rtAnchor, |
|
CFX_RectF& rtPopup) const { |
|
m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, rtPopup); |
|
} |
|
|
|
void CFWL_WidgetMgr::OnSetCapability(uint32_t dwCapability) { |
|
m_dwCapability = dwCapability; |
|
} |
|
|
|
void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) { |
|
if (!pMessage) |
|
return; |
|
if (!pMessage->m_pDstTarget) |
|
return; |
|
|
|
CFWL_Widget* pDstWidget = pMessage->m_pDstTarget; |
|
const CFWL_App* pApp = pDstWidget->GetOwnerApp(); |
|
if (!pApp) |
|
return; |
|
|
|
CFWL_NoteDriver* pNoteDriver = |
|
static_cast<CFWL_NoteDriver*>(pApp->GetNoteDriver()); |
|
if (!pNoteDriver) |
|
return; |
|
|
|
if (IsFormDisabled()) |
|
pNoteDriver->ProcessMessage(pMessage->Clone()); |
|
else |
|
pNoteDriver->QueueMessage(pMessage->Clone()); |
|
|
|
#if (_FX_OS_ == _FX_MACOSX_) |
|
CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop(); |
|
if (pTopLoop) |
|
pNoteDriver->UnqueueMessageAndProcess(pTopLoop); |
|
#endif |
|
} |
|
|
|
void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget, |
|
CFX_Graphics* pGraphics, |
|
const CFX_Matrix* pMatrix) { |
|
if (!pWidget || !pGraphics) |
|
return; |
|
|
|
CFX_RectF clipCopy(0, 0, pWidget->GetWidgetRect().Size()); |
|
CFX_RectF clipBounds; |
|
|
|
#if _FX_OS_ == _FX_MACOSX_ |
|
if (IsFormDisabled()) { |
|
#endif // _FX_OS_ == _FX_MACOSX_ |
|
|
|
pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix); |
|
clipBounds = pGraphics->GetClipRect(); |
|
clipCopy = clipBounds; |
|
|
|
#if _FX_OS_ == _FX_MACOSX_ |
|
} else { |
|
clipBounds = CFX_RectF(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d); |
|
const_cast<CFX_Matrix*>(pMatrix)->SetIdentity(); // FIXME: const cast. |
|
pWidget->GetDelegate()->OnDrawWidget(pGraphics, pMatrix); |
|
} |
|
#endif // _FX_OS_ == _FX_MACOSX_ |
|
|
|
if (!IsFormDisabled()) |
|
clipBounds.Intersect(pWidget->GetClientRect()); |
|
if (!clipBounds.IsEmpty()) |
|
DrawChild(pWidget, clipBounds, pGraphics, pMatrix); |
|
|
|
GetWidgetMgrItem(pWidget)->iRedrawCounter = 0; |
|
ResetRedrawCounts(pWidget); |
|
} |
|
|
|
void CFWL_WidgetMgr::DrawChild(CFWL_Widget* parent, |
|
const CFX_RectF& rtClip, |
|
CFX_Graphics* pGraphics, |
|
const CFX_Matrix* pMatrix) { |
|
if (!parent) |
|
return; |
|
|
|
bool bFormDisable = IsFormDisabled(); |
|
CFWL_Widget* pNextChild = GetFirstChildWidget(parent); |
|
while (pNextChild) { |
|
CFWL_Widget* child = pNextChild; |
|
pNextChild = GetNextSiblingWidget(child); |
|
if (child->GetStates() & FWL_WGTSTATE_Invisible) |
|
continue; |
|
|
|
CFX_RectF rtWidget = child->GetWidgetRect(); |
|
if (rtWidget.IsEmpty()) |
|
continue; |
|
|
|
CFX_Matrix widgetMatrix; |
|
CFX_RectF clipBounds(rtWidget); |
|
if (!bFormDisable) |
|
widgetMatrix = child->GetMatrix(); |
|
if (pMatrix) |
|
widgetMatrix.Concat(*pMatrix); |
|
|
|
if (!bFormDisable) { |
|
CFX_PointF pos = widgetMatrix.Transform(clipBounds.TopLeft()); |
|
clipBounds.left = pos.x; |
|
clipBounds.top = pos.y; |
|
clipBounds.Intersect(rtClip); |
|
if (clipBounds.IsEmpty()) |
|
continue; |
|
|
|
pGraphics->SaveGraphState(); |
|
pGraphics->SetClipRect(clipBounds); |
|
} |
|
widgetMatrix.Translate(rtWidget.left, rtWidget.top, true); |
|
|
|
if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate()) { |
|
if (IsFormDisabled() || IsNeedRepaint(child, &widgetMatrix, rtClip)) |
|
pDelegate->OnDrawWidget(pGraphics, &widgetMatrix); |
|
} |
|
if (!bFormDisable) |
|
pGraphics->RestoreGraphState(); |
|
|
|
DrawChild(child, clipBounds, pGraphics, |
|
bFormDisable ? &widgetMatrix : pMatrix); |
|
child = GetNextSiblingWidget(child); |
|
} |
|
} |
|
|
|
bool CFWL_WidgetMgr::IsNeedRepaint(CFWL_Widget* pWidget, |
|
CFX_Matrix* pMatrix, |
|
const CFX_RectF& rtDirty) { |
|
Item* pItem = GetWidgetMgrItem(pWidget); |
|
if (pItem && pItem->iRedrawCounter > 0) { |
|
pItem->iRedrawCounter = 0; |
|
return true; |
|
} |
|
|
|
CFX_RectF rtWidget(0, 0, pWidget->GetWidgetRect().Size()); |
|
pMatrix->TransformRect(rtWidget); |
|
if (!rtWidget.IntersectWith(rtDirty)) |
|
return false; |
|
|
|
CFWL_Widget* pChild = |
|
pWidget->GetOwnerApp()->GetWidgetMgr()->GetFirstChildWidget(pWidget); |
|
if (!pChild) |
|
return true; |
|
|
|
CFX_RectF rtChilds; |
|
bool bChildIntersectWithDirty = false; |
|
bool bOrginPtIntersectWidthChild = false; |
|
bool bOrginPtIntersectWidthDirty = rtDirty.Contains(rtWidget.TopLeft()); |
|
static FWL_NEEDREPAINTHITDATA hitPoint[kNeedRepaintHitPoints]; |
|
FXSYS_memset(hitPoint, 0, sizeof(hitPoint)); |
|
FX_FLOAT fxPiece = rtWidget.width / kNeedRepaintHitPiece; |
|
FX_FLOAT fyPiece = rtWidget.height / kNeedRepaintHitPiece; |
|
hitPoint[2].hitPoint.x = hitPoint[6].hitPoint.x = rtWidget.left; |
|
hitPoint[0].hitPoint.x = hitPoint[3].hitPoint.x = hitPoint[7].hitPoint.x = |
|
hitPoint[10].hitPoint.x = fxPiece + rtWidget.left; |
|
hitPoint[1].hitPoint.x = hitPoint[4].hitPoint.x = hitPoint[8].hitPoint.x = |
|
hitPoint[11].hitPoint.x = fxPiece * 2 + rtWidget.left; |
|
hitPoint[5].hitPoint.x = hitPoint[9].hitPoint.x = |
|
rtWidget.width + rtWidget.left; |
|
hitPoint[0].hitPoint.y = hitPoint[1].hitPoint.y = rtWidget.top; |
|
hitPoint[2].hitPoint.y = hitPoint[3].hitPoint.y = hitPoint[4].hitPoint.y = |
|
hitPoint[5].hitPoint.y = fyPiece + rtWidget.top; |
|
hitPoint[6].hitPoint.y = hitPoint[7].hitPoint.y = hitPoint[8].hitPoint.y = |
|
hitPoint[9].hitPoint.y = fyPiece * 2 + rtWidget.top; |
|
hitPoint[10].hitPoint.y = hitPoint[11].hitPoint.y = |
|
rtWidget.height + rtWidget.top; |
|
do { |
|
CFX_RectF rect = pChild->GetWidgetRect(); |
|
CFX_RectF r(rect.left + rtWidget.left, rect.top + rtWidget.top, rect.width, |
|
rect.height); |
|
if (r.IsEmpty()) |
|
continue; |
|
if (r.Contains(rtDirty)) |
|
return false; |
|
if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty)) |
|
bChildIntersectWithDirty = true; |
|
if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) |
|
bOrginPtIntersectWidthChild = rect.Contains(CFX_PointF(0, 0)); |
|
|
|
if (rtChilds.IsEmpty()) |
|
rtChilds = rect; |
|
else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible)) |
|
rtChilds.Union(rect); |
|
|
|
for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) { |
|
if (hitPoint[i].bNotContainByDirty || hitPoint[i].bNotNeedRepaint) |
|
continue; |
|
if (!rtDirty.Contains(hitPoint[i].hitPoint)) { |
|
hitPoint[i].bNotContainByDirty = true; |
|
continue; |
|
} |
|
if (r.Contains(hitPoint[i].hitPoint)) |
|
hitPoint[i].bNotNeedRepaint = true; |
|
} |
|
pChild = |
|
pChild->GetOwnerApp()->GetWidgetMgr()->GetNextSiblingWidget(pChild); |
|
} while (pChild); |
|
|
|
if (!bChildIntersectWithDirty) |
|
return true; |
|
if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) |
|
return true; |
|
if (rtChilds.IsEmpty()) |
|
return true; |
|
|
|
int32_t repaintPoint = kNeedRepaintHitPoints; |
|
for (int32_t i = 0; i < kNeedRepaintHitPoints; i++) { |
|
if (hitPoint[i].bNotNeedRepaint) |
|
repaintPoint--; |
|
} |
|
if (repaintPoint > 0) |
|
return true; |
|
|
|
pMatrix->TransformRect(rtChilds); |
|
if (rtChilds.Contains(rtDirty) || rtChilds.Contains(rtWidget)) |
|
return false; |
|
return true; |
|
} |
|
|
|
CFWL_WidgetMgr::Item::Item() : CFWL_WidgetMgr::Item(nullptr) {} |
|
|
|
CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) |
|
: pParent(nullptr), |
|
pOwner(nullptr), |
|
pChild(nullptr), |
|
pPrevious(nullptr), |
|
pNext(nullptr), |
|
pWidget(widget), |
|
iRedrawCounter(0) |
|
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) |
|
, |
|
bOutsideChanged(false) |
|
#endif |
|
{ |
|
} |
|
|
|
CFWL_WidgetMgr::Item::~Item() {}
|
|
|