// 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/src/foxitlib.h" | |
#include "xfa/src/fwl/src/core/include/fwl_targetimp.h" | |
#include "xfa/src/fwl/src/core/include/fwl_noteimp.h" | |
#include "xfa/src/fwl/src/core/include/fwl_widgetmgrimp.h" | |
#include "xfa/src/fwl/src/core/include/fwl_threadimp.h" | |
#include "xfa/src/fwl/src/core/include/fwl_appimp.h" | |
FX_BOOL FWL_UseOffscreen(IFWL_Widget* pWidget) { | |
#if (_FX_OS_ == _FX_MACOSX_) | |
return FALSE; | |
#else | |
return pWidget->GetStyles() & FWL_WGTSTYLE_Offscreen; | |
#endif | |
} | |
IFWL_WidgetMgr* FWL_GetWidgetMgr() { | |
IFWL_App* pApp = FWL_GetApp(); | |
if (!pApp) | |
return NULL; | |
return pApp->GetWidgetMgr(); | |
} | |
CFWL_WidgetMgr::CFWL_WidgetMgr(IFWL_AdapterNative* pAdapterNative) | |
: m_dwCapability(0) { | |
m_pDelegate = new CFWL_WidgetMgrDelegate(this); | |
m_pAdapter = pAdapterNative->GetWidgetMgr(m_pDelegate); | |
FXSYS_assert(m_pAdapter); | |
CFWL_WidgetMgrItem* pRoot = new CFWL_WidgetMgrItem; | |
m_mapWidgetItem.SetAt(NULL, pRoot); | |
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
m_rtScreen.Reset(); | |
IFWL_AdapterMonitorMgr* pMonitorMgr = pAdapterNative->GetMonitorMgr(); | |
if (pMonitorMgr) { | |
FWL_HMONITOR monitor = pMonitorMgr->GetCurrentMonitor(); | |
if (monitor) { | |
pMonitorMgr->GetMonitorSize(monitor, m_rtScreen.width, m_rtScreen.height); | |
} | |
} | |
#endif | |
} | |
CFWL_WidgetMgr::~CFWL_WidgetMgr() { | |
FX_POSITION ps = m_mapWidgetItem.GetStartPosition(); | |
while (ps) { | |
void* pWidget; | |
CFWL_WidgetMgrItem* pItem; | |
m_mapWidgetItem.GetNextAssoc(ps, pWidget, (void*&)pItem); | |
delete pItem; | |
} | |
m_mapWidgetItem.RemoveAll(); | |
if (m_pDelegate) { | |
delete m_pDelegate; | |
m_pDelegate = NULL; | |
} | |
} | |
int32_t CFWL_WidgetMgr::CountWidgets(IFWL_Widget* pParent) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
return TravelWidgetMgr(pParentItem, NULL, NULL); | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetWidget(int32_t nIndex, IFWL_Widget* pParent) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
IFWL_Widget* pWidget = NULL; | |
TravelWidgetMgr(pParentItem, &nIndex, NULL, &pWidget); | |
return pWidget; | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetWidget(IFWL_Widget* pWidget, | |
FWL_WGTRELATION eRelation) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
if (!pItem) { | |
return NULL; | |
} | |
IFWL_Widget* pRet = NULL; | |
switch (eRelation) { | |
case FWL_WGTRELATION_Parent: { | |
pRet = pItem->pParent ? pItem->pParent->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_Owner: { | |
pRet = pItem->pOwner ? pItem->pOwner->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_FirstSibling: { | |
pItem = pItem->pPrevious; | |
while (pItem && pItem->pPrevious) { | |
pItem = pItem->pPrevious; | |
} | |
pRet = pItem ? pItem->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_PriorSibling: { | |
pRet = pItem->pPrevious ? pItem->pPrevious->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_NextSibling: { | |
pRet = pItem->pNext ? pItem->pNext->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_LastSibling: { | |
pItem = pItem->pNext; | |
while (pItem && pItem->pNext) { | |
pItem = pItem->pNext; | |
} | |
pRet = pItem ? pItem->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_FirstChild: { | |
pRet = pItem->pChild ? pItem->pChild->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_LastChild: { | |
pItem = pItem->pChild; | |
while (pItem && pItem->pNext) { | |
pItem = pItem->pNext; | |
} | |
pRet = pItem ? pItem->pWidget : NULL; | |
break; | |
} | |
case FWL_WGTRELATION_SystemForm: { | |
while (pItem) { | |
if (IsAbleNative(pItem->pWidget)) { | |
pRet = pItem->pWidget; | |
break; | |
} | |
pItem = pItem->pParent; | |
} | |
break; | |
} | |
default: {} | |
} | |
return pRet; | |
} | |
int32_t CFWL_WidgetMgr::GetWidgetIndex(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
if (!pItem) | |
return -1; | |
return TravelWidgetMgr(pItem->pParent, NULL, pItem); | |
} | |
FX_BOOL CFWL_WidgetMgr::SetWidgetIndex(IFWL_Widget* pWidget, int32_t nIndex) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
if (!pItem) | |
return FALSE; | |
if (!pItem->pParent) | |
return FALSE; | |
CFWL_WidgetMgrItem* pChild = pItem->pParent->pChild; | |
int32_t i = 0; | |
while (pChild) { | |
if (pChild == pItem) { | |
if (i == nIndex) { | |
return TRUE; | |
} | |
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 = NULL; | |
pItem->pPrevious = NULL; | |
break; | |
} | |
if (!pChild->pNext) { | |
break; | |
} | |
pChild = pChild->pNext; | |
++i; | |
} | |
pChild = pItem->pParent->pChild; | |
if (pChild) { | |
if (nIndex < 0) { | |
while (pChild->pNext) { | |
pChild = pChild->pNext; | |
} | |
pChild->pNext = pItem; | |
pItem->pPrevious = pChild; | |
pItem->pNext = NULL; | |
return TRUE; | |
} | |
i = 0; | |
while (i < nIndex && pChild->pNext) { | |
pChild = pChild->pNext; | |
++i; | |
} | |
if (!pChild->pNext) { | |
pChild->pNext = pItem; | |
pItem->pPrevious = pChild; | |
pItem->pNext = NULL; | |
return TRUE; | |
} | |
if (pChild->pPrevious) { | |
pItem->pPrevious = pChild->pPrevious; | |
pChild->pPrevious->pNext = pItem; | |
} | |
pChild->pPrevious = pItem; | |
pItem->pNext = pChild; | |
if (pItem->pParent->pChild == pChild) { | |
pItem->pParent->pChild = pItem; | |
} | |
} else { | |
pItem->pParent->pChild = pItem; | |
pItem->pPrevious = NULL; | |
pItem->pNext = NULL; | |
} | |
return TRUE; | |
} | |
FWL_ERR CFWL_WidgetMgr::RepaintWidget(IFWL_Widget* pWidget, | |
const CFX_RectF* pRect) { | |
if (!m_pAdapter) | |
return FWL_ERR_Indefinite; | |
IFWL_Widget* pNative = pWidget; | |
CFX_RectF rect(*pRect); | |
if (IsFormDisabled()) { | |
IFWL_Widget* pOuter = pWidget->GetOuter(); | |
while (pOuter) { | |
CFX_RectF rtTemp; | |
pNative->GetWidgetRect(rtTemp); | |
rect.left += rtTemp.left; | |
rect.top += rtTemp.top; | |
pNative = pOuter; | |
pOuter = pOuter->GetOuter(); | |
} | |
} else if (!IsAbleNative(pWidget)) { | |
pNative = GetWidget(pWidget, FWL_WGTRELATION_SystemForm); | |
if (!pNative) | |
return FWL_ERR_Indefinite; | |
pWidget->TransformTo(pNative, rect.left, rect.top); | |
} | |
AddRedrawCounts(pNative); | |
return m_pAdapter->RepaintWidget(pNative, &rect); | |
} | |
void CFWL_WidgetMgr::AddWidget(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(NULL); | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
if (!pItem) { | |
pItem = new CFWL_WidgetMgrItem; | |
pItem->pWidget = pWidget; | |
m_mapWidgetItem.SetAt(pWidget, pItem); | |
} | |
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; | |
SetWidgetIndex(pWidget, -1); | |
} | |
void CFWL_WidgetMgr::InsertWidget(IFWL_Widget* pParent, | |
IFWL_Widget* pChild, | |
int32_t nIndex) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
if (!pParentItem) { | |
pParentItem = new CFWL_WidgetMgrItem; | |
pParentItem->pWidget = pParent; | |
m_mapWidgetItem.SetAt(pParent, pParentItem); | |
CFWL_WidgetMgrItem* pRoot = GetWidgetMgrItem(NULL); | |
pParentItem->pParent = pRoot; | |
SetWidgetIndex(pParent, -1); | |
} | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pChild); | |
if (!pItem) { | |
pItem = new CFWL_WidgetMgrItem; | |
pItem->pWidget = pChild; | |
m_mapWidgetItem.SetAt(pChild, pItem); | |
} | |
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; | |
SetWidgetIndex(pChild, nIndex); | |
} | |
void CFWL_WidgetMgr::RemoveWidget(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* 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; | |
} | |
CFWL_WidgetMgrItem* pChild = pItem->pChild; | |
while (pChild) { | |
CFWL_WidgetMgrItem* pNext = pChild->pNext; | |
RemoveWidget(pChild->pWidget); | |
pChild = pNext; | |
} | |
m_mapWidgetItem.RemoveKey(pWidget); | |
delete pItem; | |
} | |
void CFWL_WidgetMgr::SetOwner(IFWL_Widget* pOwner, IFWL_Widget* pOwned) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pOwner); | |
if (!pParentItem) { | |
pParentItem = new CFWL_WidgetMgrItem; | |
pParentItem->pWidget = pOwner; | |
m_mapWidgetItem.SetAt(pOwner, pParentItem); | |
CFWL_WidgetMgrItem* pRoot = GetWidgetMgrItem(NULL); | |
pParentItem->pParent = pRoot; | |
SetWidgetIndex(pOwner, -1); | |
} | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pOwned); | |
if (!pItem) { | |
pItem = new CFWL_WidgetMgrItem; | |
pItem->pWidget = pOwned; | |
m_mapWidgetItem.SetAt(pOwned, pItem); | |
} | |
pItem->pOwner = pParentItem; | |
} | |
void CFWL_WidgetMgr::SetParent(IFWL_Widget* pParent, IFWL_Widget* pChild) { | |
CFWL_WidgetMgrItem* pParentItem = GetWidgetMgrItem(pParent); | |
CFWL_WidgetMgrItem* 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 = NULL; | |
pItem->pPrevious = NULL; | |
} | |
pItem->pParent = pParentItem; | |
SetWidgetIndex(pChild, -1); | |
if (!m_pAdapter) | |
return; | |
m_pAdapter->SetParentWidget(pChild, pParent); | |
} | |
FX_BOOL CFWL_WidgetMgr::IsChild(IFWL_Widget* pChild, IFWL_Widget* pParent) { | |
IFWL_Widget* pTemp = pChild; | |
do { | |
if (pTemp == pParent) { | |
return TRUE; | |
} | |
pTemp = GetWidget(pTemp, FWL_WGTRELATION_Parent); | |
} while (pTemp); | |
return FALSE; | |
} | |
FWL_ERR CFWL_WidgetMgr::CreateWidget_Native(IFWL_Widget* pWidget) { | |
if (!IsAbleNative(pWidget)) { | |
return FWL_ERR_Succeeded; | |
} | |
return m_pAdapter->CreateWidget(pWidget, pWidget->GetOwner()); | |
} | |
FWL_ERR CFWL_WidgetMgr::DestroyWidget_Native(IFWL_Widget* pWidget) { | |
if (!IsAbleNative(pWidget)) { | |
return FWL_ERR_Succeeded; | |
} | |
return m_pAdapter->DestroyWidget(pWidget); | |
} | |
FWL_ERR CFWL_WidgetMgr::GetWidgetRect_Native(IFWL_Widget* pWidget, | |
CFX_RectF& rect) { | |
if (!IsAbleNative(pWidget)) { | |
return FWL_ERR_Succeeded; | |
} | |
return m_pAdapter->GetWidgetRect(pWidget, rect); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetWidgetRect_Native(IFWL_Widget* pWidget, | |
const CFX_RectF& rect) { | |
if (FWL_UseOffscreen(pWidget)) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
pItem->iRedrawCounter++; | |
if (pItem->pOffscreen) { | |
CFX_RenderDevice* pDevice = pItem->pOffscreen->GetRenderDevice(); | |
if (pDevice && pDevice->GetBitmap()) { | |
CFX_DIBitmap* pBitmap = pDevice->GetBitmap(); | |
if (pBitmap->GetWidth() - rect.width > 1 || | |
pBitmap->GetHeight() - rect.height > 1) { | |
delete pItem->pOffscreen; | |
pItem->pOffscreen = NULL; | |
} | |
} | |
} | |
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
pItem->bOutsideChanged = !m_rtScreen.Contains(rect); | |
#endif | |
} | |
return m_pAdapter->SetWidgetRect(pWidget, rect); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetWidgetPosition_Native(IFWL_Widget* pWidget, | |
FX_FLOAT fx, | |
FX_FLOAT fy) { | |
return m_pAdapter->SetWidgetPosition(pWidget, fx, fy); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetWidgetIcon_Native(IFWL_Widget* pWidget, | |
const CFX_DIBitmap* pIcon, | |
FX_BOOL bBig) { | |
return m_pAdapter->SetWidgetIcon(pWidget, pIcon, bBig); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetWidgetCaption_Native( | |
IFWL_Widget* pWidget, | |
const CFX_WideStringC& wsCaption) { | |
return m_pAdapter->SetWidgetCaption(pWidget, wsCaption); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetBorderRegion_Native(IFWL_Widget* pWidget, | |
CFX_Path* pPath) { | |
return m_pAdapter->SetBorderRegion(pWidget, pPath); | |
} | |
FWL_ERR CFWL_WidgetMgr::ShowWidget_Native(IFWL_Widget* pWidget) { | |
return m_pAdapter->ShowWidget(pWidget); | |
} | |
FWL_ERR CFWL_WidgetMgr::HideWidget_Native(IFWL_Widget* pWidget) { | |
return m_pAdapter->HideWidget(pWidget); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetNormal_Native(IFWL_Widget* pWidget) { | |
return m_pAdapter->SetNormal(pWidget); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetMaximize_Native(IFWL_Widget* pWidget) { | |
return m_pAdapter->SetMaximize(pWidget); | |
} | |
FWL_ERR CFWL_WidgetMgr::SetMinimize_Native(IFWL_Widget* pWidget) { | |
return m_pAdapter->SetMinimize(pWidget); | |
} | |
FX_BOOL CFWL_WidgetMgr::CheckMessage_Native() { | |
return m_pAdapter->CheckMessage(); | |
} | |
FWL_ERR CFWL_WidgetMgr::DispatchMessage_Native() { | |
return m_pAdapter->DispatchMessage(); | |
} | |
FX_BOOL CFWL_WidgetMgr::IsIdleMessage_Native() { | |
return m_pAdapter->IsIdleMessage(); | |
} | |
FWL_ERR CFWL_WidgetMgr::Exit_Native(int32_t iExitCode) { | |
return m_pAdapter->Exit(iExitCode); | |
} | |
FWL_ERR CFWL_WidgetMgr::CreateWidgetWithNativeId_Native(IFWL_Widget* pWidget, | |
void* vp) { | |
return m_pAdapter->CreateWidgetWithNativeId(pWidget, vp); | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(IFWL_Widget* parent, | |
FX_FLOAT x, | |
FX_FLOAT y) { | |
if (!parent) | |
return NULL; | |
FX_FLOAT x1; | |
FX_FLOAT y1; | |
IFWL_Widget* child = GetWidget(parent, FWL_WGTRELATION_LastChild); | |
while (child) { | |
if ((child->GetStates() & FWL_WGTSTATE_Invisible) == 0) { | |
x1 = x; | |
y1 = y; | |
CFX_Matrix matrixOnParent; | |
child->GetMatrix(matrixOnParent); | |
CFX_Matrix m; | |
m.SetIdentity(); | |
m.SetReverse(matrixOnParent); | |
m.TransformPoint(x1, y1); | |
CFX_RectF bounds; | |
child->GetWidgetRect(bounds); | |
if (bounds.Contains(x1, y1)) { | |
x1 -= bounds.left; | |
y1 -= bounds.top; | |
return GetWidgetAtPoint(child, x1, y1); | |
} | |
} | |
child = GetWidget(child, FWL_WGTRELATION_PriorSibling); | |
} | |
return parent; | |
} | |
void CFWL_WidgetMgr::NotifySizeChanged(IFWL_Widget* pForm, | |
FX_FLOAT fx, | |
FX_FLOAT fy) { | |
if (!FWL_UseOffscreen(pForm)) { | |
return; | |
} | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pForm); | |
if (pItem->pOffscreen) { | |
delete pItem->pOffscreen; | |
pItem->pOffscreen = NULL; | |
} | |
} | |
IFWL_Widget* CFWL_WidgetMgr::nextTab(IFWL_Widget* parent, | |
IFWL_Widget* focus, | |
FX_BOOL& bFind) { | |
IFWL_Widget* child = | |
FWL_GetWidgetMgr()->GetWidget(parent, FWL_WGTRELATION_FirstChild); | |
while (child) { | |
if (focus == child) { | |
bFind = TRUE; | |
} | |
if ((child->GetStyles() & FWL_WGTSTYLE_TabStop) && | |
(!focus || (focus != child && bFind))) { | |
return child; | |
} | |
IFWL_Widget* bRet = nextTab(child, focus, bFind); | |
if (bRet) { | |
return bRet; | |
} | |
child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling); | |
} | |
return NULL; | |
} | |
int32_t CFWL_WidgetMgr::CountRadioButtonGroup(IFWL_Widget* pFirst) { | |
int32_t iRet = 0; | |
IFWL_Widget* pChild = pFirst; | |
while (pChild) { | |
if ((pChild->GetStyles() & FWL_WGTSTYLE_Group) && | |
pChild->GetClassID() == 3811304691) { | |
iRet++; | |
} | |
pChild = GetWidget(pChild, FWL_WGTRELATION_NextSibling); | |
} | |
return iRet; | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetSiblingRadioButton(IFWL_Widget* pWidget, | |
FX_BOOL bNext) { | |
while ((pWidget = GetWidget(pWidget, bNext ? FWL_WGTRELATION_NextSibling | |
: FWL_WGTRELATION_PriorSibling)) != | |
NULL) { | |
if (pWidget->GetClassID() == 3811304691) { | |
return pWidget; | |
} | |
} | |
return NULL; | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetRadioButtonGroupHeader( | |
IFWL_Widget* pRadioButton) { | |
if (pRadioButton->GetStyles() & FWL_WGTSTYLE_Group) { | |
return pRadioButton; | |
} | |
IFWL_Widget* pNext = pRadioButton; | |
while ((pNext = GetSiblingRadioButton(pNext, FALSE)) != NULL) { | |
if (pNext->GetStyles() & FWL_WGTSTYLE_Group) { | |
return pNext; | |
} | |
} | |
pNext = GetWidget(pRadioButton, FWL_WGTRELATION_LastSibling); | |
if ((pNext->GetStyles() & FWL_WGTSTYLE_Group) && | |
pNext->GetClassID() == 3811304691) { | |
return pNext; | |
} | |
while ((pNext = GetSiblingRadioButton(pNext, FALSE)) && pNext && | |
pNext != pRadioButton) { | |
if (pNext->GetStyles() & FWL_WGTSTYLE_Group) { | |
return pNext; | |
} | |
} | |
pNext = GetWidget(pRadioButton, FWL_WGTRELATION_FirstSibling); | |
if (pNext && (pNext->GetStyles() == FWL_WGTSTYLE_Group) && | |
pNext->GetClassID() == 3811304691) { | |
return pNext; | |
} | |
return GetSiblingRadioButton(pNext, TRUE); | |
} | |
void CFWL_WidgetMgr::GetSameGroupRadioButton(IFWL_Widget* pRadioButton, | |
CFX_PtrArray& group) { | |
IFWL_Widget* pFirst = GetWidget(pRadioButton, FWL_WGTRELATION_FirstSibling); | |
if (!pFirst) { | |
pFirst = pRadioButton; | |
} | |
int32_t iGroup = CountRadioButtonGroup(pFirst); | |
if (iGroup < 2) { | |
if (pFirst->GetClassID() == 3811304691) { | |
group.Add(pFirst); | |
} | |
IFWL_Widget* pNext = pFirst; | |
while ((pNext = GetSiblingRadioButton(pNext, TRUE)) != NULL) { | |
group.Add(pNext); | |
} | |
return; | |
} | |
IFWL_Widget* pNext = GetRadioButtonGroupHeader(pRadioButton); | |
do { | |
group.Add(pNext); | |
pNext = GetSiblingRadioButton(pNext, TRUE); | |
if (!pNext) { | |
if (pFirst->GetClassID() == 3811304691) { | |
pNext = pFirst; | |
} else { | |
pNext = GetSiblingRadioButton(pFirst, TRUE); | |
} | |
} | |
} while (pNext && ((pNext->GetStyles() & FWL_WGTSTYLE_Group) == 0)); | |
} | |
IFWL_Widget* CFWL_WidgetMgr::GetDefaultButton(IFWL_Widget* pParent) { | |
if ((pParent->GetClassID() == 3521614244) && | |
(pParent->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { | |
return pParent; | |
} | |
IFWL_Widget* child = | |
FWL_GetWidgetMgr()->GetWidget(pParent, FWL_WGTRELATION_FirstChild); | |
while (child) { | |
if ((child->GetClassID() == 3521614244) && | |
(child->GetStates() & (1 << (FWL_WGTSTATE_MAX + 2)))) { | |
return child; | |
} | |
IFWL_Widget* find = GetDefaultButton(child); | |
if (find) { | |
return find; | |
} | |
child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling); | |
} | |
return NULL; | |
} | |
void CFWL_WidgetMgr::AddRedrawCounts(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
(pItem->iRedrawCounter)++; | |
} | |
void CFWL_WidgetMgr::ResetRedrawCounts(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* pItem = GetWidgetMgrItem(pWidget); | |
pItem->iRedrawCounter = 0; | |
} | |
CFWL_WidgetMgrItem* CFWL_WidgetMgr::GetWidgetMgrItem(IFWL_Widget* pWidget) { | |
return static_cast<CFWL_WidgetMgrItem*>(m_mapWidgetItem.GetValueAt(pWidget)); | |
} | |
int32_t CFWL_WidgetMgr::TravelWidgetMgr(CFWL_WidgetMgrItem* pParent, | |
int32_t* pIndex, | |
CFWL_WidgetMgrItem* pItem, | |
IFWL_Widget** pWidget) { | |
if (!pParent) { | |
return 0; | |
} | |
int32_t iCount = 0; | |
CFWL_WidgetMgrItem* pChild = pParent->pChild; | |
while (pChild) { | |
iCount++; | |
if (pIndex) { | |
if (*pIndex == 0) { | |
*pWidget = pChild->pWidget; | |
return iCount; | |
} | |
pIndex--; | |
} | |
if (pItem && pItem == pChild) { | |
return iCount - 1; | |
} | |
pChild = pChild->pNext; | |
} | |
if (pIndex) { | |
return 0; | |
} else if (pItem) { | |
return -1; | |
} | |
return iCount - 1; | |
} | |
FX_BOOL CFWL_WidgetMgr::IsAbleNative(IFWL_Widget* pWidget) { | |
if (!pWidget) | |
return FALSE; | |
if (!pWidget->IsInstance(FX_WSTRC(FWL_CLASS_Form))) { | |
return FALSE; | |
} | |
FX_DWORD dwStyles = pWidget->GetStyles(); | |
return ((dwStyles & FWL_WGTSTYLE_WindowTypeMask) == | |
FWL_WGTSTYLE_OverLapper) || | |
(dwStyles & FWL_WGTSTYLE_Popup); | |
} | |
FX_BOOL CFWL_WidgetMgr::IsThreadEnabled() { | |
return !(m_dwCapability & FWL_WGTMGR_DisableThread); | |
} | |
FX_BOOL CFWL_WidgetMgr::IsFormDisabled() { | |
return m_dwCapability & FWL_WGTMGR_DisableForm; | |
} | |
FX_BOOL CFWL_WidgetMgr::GetAdapterPopupPos(IFWL_Widget* pWidget, | |
FX_FLOAT fMinHeight, | |
FX_FLOAT fMaxHeight, | |
const CFX_RectF& rtAnchor, | |
CFX_RectF& rtPopup) { | |
IFWL_AdapterWidgetMgr* pSDApapter = GetAdapterWidgetMgr(); | |
return pSDApapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor, | |
rtPopup); | |
} | |
CFWL_WidgetMgrDelegate::CFWL_WidgetMgrDelegate(CFWL_WidgetMgr* pWidgetMgr) | |
: m_pWidgetMgr(pWidgetMgr) {} | |
FWL_ERR CFWL_WidgetMgrDelegate::OnSetCapability(FX_DWORD dwCapability) { | |
m_pWidgetMgr->m_dwCapability = dwCapability; | |
return FWL_ERR_Succeeded; | |
} | |
int32_t CFWL_WidgetMgrDelegate::OnProcessMessageToForm(CFWL_Message* pMessage) { | |
if (!pMessage) | |
return 0; | |
if (!pMessage->m_pDstTarget) | |
return 0; | |
IFWL_Widget* pDstWidget = pMessage->m_pDstTarget; | |
IFWL_NoteThread* pNoteThread = pDstWidget->GetOwnerThread(); | |
if (!pNoteThread) | |
return 0; | |
CFWL_NoteDriver* pNoteDriver = | |
static_cast<CFWL_NoteDriver*>(pNoteThread->GetNoteDriver()); | |
if (!pNoteDriver) | |
return 0; | |
if (m_pWidgetMgr->IsThreadEnabled()) { | |
pMessage = static_cast<CFWL_Message*>(pMessage->Clone()); | |
} | |
if (m_pWidgetMgr->IsFormDisabled()) { | |
pNoteDriver->ProcessMessage(pMessage); | |
} else { | |
pNoteDriver->QueueMessage(pMessage); | |
} | |
#if (_FX_OS_ == _FX_MACOSX_) | |
CFWL_NoteLoop* pTopLoop = pNoteDriver->GetTopLoop(); | |
if (pTopLoop) { | |
pNoteDriver->UnqueueMessage(pTopLoop); | |
} | |
#endif | |
if (m_pWidgetMgr->IsThreadEnabled()) { | |
pMessage->Release(); | |
} | |
return FWL_ERR_Succeeded; | |
} | |
FWL_ERR CFWL_WidgetMgrDelegate::OnDrawWidget(IFWL_Widget* pWidget, | |
CFX_Graphics* pGraphics, | |
const CFX_Matrix* pMatrix) { | |
if (!pWidget) | |
return FWL_ERR_Indefinite; | |
if (!pGraphics) | |
return FWL_ERR_Indefinite; | |
CFX_Graphics* pTemp = DrawWidgetBefore(pWidget, pGraphics, pMatrix); | |
CFX_RectF clipCopy; | |
pWidget->GetWidgetRect(clipCopy); | |
clipCopy.left = clipCopy.top = 0; | |
if (bUseOffscreenDirect(pWidget)) { | |
DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix); | |
return FWL_ERR_Succeeded; | |
} | |
CFX_RectF clipBounds; | |
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) || \ | |
(_FX_OS_ == _FX_LINUX_DESKTOP_) || (_FX_OS_ == _FX_ANDROID_) | |
IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
pDelegate->OnDrawWidget(pTemp, pMatrix); | |
pGraphics->GetClipRect(clipBounds); | |
clipCopy = clipBounds; | |
#elif(_FX_OS_ == _FX_MACOSX_) | |
if (m_pWidgetMgr->IsFormDisabled()) { | |
IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
pDelegate->OnDrawWidget(pTemp, pMatrix); | |
pGraphics->GetClipRect(clipBounds); | |
clipCopy = clipBounds; | |
} else { | |
clipBounds.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d); | |
const_cast<CFX_Matrix*>(pMatrix)->SetIdentity(); // FIXME: const cast. | |
#ifdef FWL_UseMacSystemBorder | |
#else | |
#endif | |
{ | |
IFWL_WidgetDelegate* pDelegate = pWidget->SetDelegate(NULL); | |
pDelegate->OnDrawWidget(pTemp, pMatrix); | |
} | |
} | |
#endif | |
if (!m_pWidgetMgr->IsFormDisabled()) { | |
CFX_RectF rtClient; | |
pWidget->GetClientRect(rtClient); | |
clipBounds.Intersect(rtClient); | |
} | |
if (!clipBounds.IsEmpty()) { | |
DrawChild(pWidget, clipBounds, pTemp, pMatrix); | |
} | |
DrawWidgetAfter(pWidget, pGraphics, clipCopy, pMatrix); | |
m_pWidgetMgr->ResetRedrawCounts(pWidget); | |
return FWL_ERR_Succeeded; | |
} | |
void CFWL_WidgetMgrDelegate::DrawChild(IFWL_Widget* parent, | |
const CFX_RectF& rtClip, | |
CFX_Graphics* pGraphics, | |
const CFX_Matrix* pMatrix) { | |
if (!parent) | |
return; | |
FX_BOOL bFormDisable = m_pWidgetMgr->IsFormDisabled(); | |
IFWL_Widget* pNextChild = | |
m_pWidgetMgr->GetWidget(parent, FWL_WGTRELATION_FirstChild); | |
while (pNextChild) { | |
IFWL_Widget* child = pNextChild; | |
pNextChild = m_pWidgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling); | |
if (child->GetStates() & FWL_WGTSTATE_Invisible) { | |
continue; | |
} | |
CFX_RectF rtWidget; | |
child->GetWidgetRect(rtWidget); | |
if (rtWidget.IsEmpty()) { | |
continue; | |
} | |
CFX_Matrix widgetMatrix; | |
CFX_RectF clipBounds(rtWidget); | |
if (!bFormDisable) { | |
child->GetMatrix(widgetMatrix, TRUE); | |
} | |
if (pMatrix) { | |
widgetMatrix.Concat(*pMatrix); | |
} | |
if (!bFormDisable) { | |
widgetMatrix.TransformPoint(clipBounds.left, clipBounds.top); | |
clipBounds.Intersect(rtClip); | |
if (clipBounds.IsEmpty()) { | |
continue; | |
} | |
pGraphics->SaveGraphState(); | |
pGraphics->SetClipRect(clipBounds); | |
} | |
widgetMatrix.Translate(rtWidget.left, rtWidget.top, TRUE); | |
IFWL_WidgetDelegate* pDelegate = child->SetDelegate(NULL); | |
if (pDelegate) { | |
if (m_pWidgetMgr->IsFormDisabled() || | |
IsNeedRepaint(child, &widgetMatrix, rtClip)) { | |
pDelegate->OnDrawWidget(pGraphics, &widgetMatrix); | |
} | |
} | |
if (!bFormDisable) { | |
pGraphics->RestoreGraphState(); | |
} | |
DrawChild(child, clipBounds, pGraphics, | |
bFormDisable ? &widgetMatrix : pMatrix); | |
child = m_pWidgetMgr->GetWidget(child, FWL_WGTRELATION_NextSibling); | |
} | |
} | |
CFX_Graphics* CFWL_WidgetMgrDelegate::DrawWidgetBefore( | |
IFWL_Widget* pWidget, | |
CFX_Graphics* pGraphics, | |
const CFX_Matrix* pMatrix) { | |
if (!FWL_UseOffscreen(pWidget)) { | |
return pGraphics; | |
} | |
CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
if (!pItem->pOffscreen) { | |
pItem->pOffscreen = new CFX_Graphics; | |
CFX_RectF rect; | |
pWidget->GetWidgetRect(rect); | |
pItem->pOffscreen->Create((int32_t)rect.width, (int32_t)rect.height, | |
FXDIB_Argb); | |
} | |
CFX_RectF rect; | |
pGraphics->GetClipRect(rect); | |
pItem->pOffscreen->SetClipRect(rect); | |
return pItem->pOffscreen; | |
} | |
void CFWL_WidgetMgrDelegate::DrawWidgetAfter(IFWL_Widget* pWidget, | |
CFX_Graphics* pGraphics, | |
CFX_RectF& rtClip, | |
const CFX_Matrix* pMatrix) { | |
if (FWL_UseOffscreen(pWidget)) { | |
CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
pGraphics->Transfer(pItem->pOffscreen, rtClip.left, rtClip.top, rtClip, | |
pMatrix); | |
#ifdef _WIN32 | |
pItem->pOffscreen->ClearClip(); | |
#endif | |
} | |
CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
pItem->iRedrawCounter = 0; | |
} | |
#define FWL_NEEDREPAINTHIT_Point 12 | |
#define FWL_NEEDREPAINTHIT_Piece 3 | |
typedef struct _FWL_NeedRepaintHitData { | |
CFX_PointF hitPoint; | |
FX_BOOL bNotNeedRepaint; | |
FX_BOOL bNotContainByDirty; | |
} FWL_NeedRepaintHitData; | |
FX_BOOL CFWL_WidgetMgrDelegate::IsNeedRepaint(IFWL_Widget* pWidget, | |
CFX_Matrix* pMatrix, | |
const CFX_RectF& rtDirty) { | |
CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
if (pItem && pItem->iRedrawCounter > 0) { | |
pItem->iRedrawCounter = 0; | |
return TRUE; | |
} | |
CFX_RectF rtWidget; | |
pWidget->GetWidgetRect(rtWidget); | |
rtWidget.left = rtWidget.top = 0; | |
pMatrix->TransformRect(rtWidget); | |
if (!rtWidget.IntersectWith(rtDirty)) { | |
return FALSE; | |
} | |
IFWL_Widget* pChild = | |
FWL_GetWidgetMgr()->GetWidget(pWidget, FWL_WGTRELATION_FirstChild); | |
if (!pChild) { | |
return TRUE; | |
} | |
if (pChild->GetClassID() == 3150298670) { | |
CFX_RectF rtTemp; | |
pChild->GetWidgetRect(rtTemp); | |
if (rtTemp.width >= rtWidget.width && rtTemp.height >= rtWidget.height) { | |
pChild = | |
FWL_GetWidgetMgr()->GetWidget(pChild, FWL_WGTRELATION_FirstChild); | |
if (!pChild) { | |
return TRUE; | |
} | |
} | |
} | |
CFX_RectF rtChilds; | |
rtChilds.Empty(); | |
FX_BOOL bChildIntersectWithDirty = FALSE; | |
FX_BOOL bOrginPtIntersectWidthChild = FALSE; | |
FX_BOOL bOrginPtIntersectWidthDirty = | |
rtDirty.Contains(rtWidget.left, rtWidget.top); | |
static FWL_NeedRepaintHitData hitPoint[FWL_NEEDREPAINTHIT_Point]; | |
static int32_t iSize = sizeof(FWL_NeedRepaintHitData); | |
FXSYS_memset(hitPoint, 0, iSize); | |
FX_FLOAT fxPiece = rtWidget.width / FWL_NEEDREPAINTHIT_Piece; | |
FX_FLOAT fyPiece = rtWidget.height / FWL_NEEDREPAINTHIT_Piece; | |
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(rect); | |
CFX_RectF r = rect; | |
r.left += rtWidget.left; | |
r.top += rtWidget.top; | |
if (r.IsEmpty()) { | |
continue; | |
} | |
if (r.Contains(rtDirty)) { | |
return FALSE; | |
} | |
if (!bChildIntersectWithDirty && r.IntersectWith(rtDirty)) { | |
bChildIntersectWithDirty = TRUE; | |
} | |
if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) { | |
bOrginPtIntersectWidthChild = rect.Contains(0, 0); | |
} | |
if (rtChilds.IsEmpty()) { | |
rtChilds = rect; | |
} else if (!(pChild->GetStates() & FWL_WGTSTATE_Invisible)) { | |
rtChilds.Union(rect); | |
} | |
for (int32_t i = 0; i < FWL_NEEDREPAINTHIT_Point; 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; | |
} | |
} | |
} while ((pChild = FWL_GetWidgetMgr()->GetWidget( | |
pChild, FWL_WGTRELATION_NextSibling)) != NULL); | |
if (!bChildIntersectWithDirty) { | |
return TRUE; | |
} | |
if (bOrginPtIntersectWidthDirty && !bOrginPtIntersectWidthChild) { | |
return TRUE; | |
} | |
if (rtChilds.IsEmpty()) { | |
return TRUE; | |
} | |
int32_t repaintPoint = FWL_NEEDREPAINTHIT_Point; | |
for (int32_t i = 0; i < FWL_NEEDREPAINTHIT_Point; 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; | |
} | |
FX_BOOL CFWL_WidgetMgrDelegate::bUseOffscreenDirect(IFWL_Widget* pWidget) { | |
CFWL_WidgetMgrItem* pItem = m_pWidgetMgr->GetWidgetMgrItem(pWidget); | |
if (!FWL_UseOffscreen(pWidget) || !(pItem->pOffscreen)) { | |
return FALSE; | |
} | |
#if (_FX_OS_ == _FX_WIN32_DESKTOP_) || (_FX_OS_ == _FX_WIN64_) | |
if (pItem->bOutsideChanged) { | |
CFX_RectF r; | |
pWidget->GetWidgetRect(r); | |
CFX_RectF temp(m_pWidgetMgr->m_rtScreen); | |
temp.Deflate(50, 50); | |
if (!temp.Contains(r)) { | |
return FALSE; | |
} | |
pItem->bOutsideChanged = FALSE; | |
} | |
#endif | |
return pItem->iRedrawCounter == 0; | |
} | |
static void FWL_WriteBMP(CFX_DIBitmap* pBitmap, const FX_CHAR* filename) { | |
FILE* file = fopen(filename, "wb"); | |
if (file == NULL) { | |
return; | |
} | |
int size = 14 + 40 + pBitmap->GetPitch() * pBitmap->GetHeight(); | |
unsigned char buffer[40]; | |
buffer[0] = 'B'; | |
buffer[1] = 'M'; | |
buffer[2] = (unsigned char)size; | |
buffer[3] = (unsigned char)(size >> 8); | |
buffer[4] = (unsigned char)(size >> 16); | |
buffer[5] = (unsigned char)(size >> 24); | |
buffer[6] = buffer[7] = buffer[8] = buffer[9] = 0; | |
buffer[10] = 54; | |
buffer[11] = buffer[12] = buffer[13] = 0; | |
fwrite(buffer, 14, 1, file); | |
memset(buffer, 0, 40); | |
buffer[0] = 40; | |
buffer[4] = (unsigned char)pBitmap->GetWidth(); | |
buffer[5] = (unsigned char)(pBitmap->GetWidth() >> 8); | |
buffer[6] = (unsigned char)(pBitmap->GetWidth() >> 16); | |
buffer[7] = (unsigned char)(pBitmap->GetWidth() >> 24); | |
buffer[8] = (unsigned char)(-pBitmap->GetHeight()); | |
buffer[9] = (unsigned char)((-pBitmap->GetHeight()) >> 8); | |
buffer[10] = (unsigned char)((-pBitmap->GetHeight()) >> 16); | |
buffer[11] = (unsigned char)((-pBitmap->GetHeight()) >> 24); | |
buffer[12] = 1; | |
buffer[14] = pBitmap->GetBPP(); | |
fwrite(buffer, 40, 1, file); | |
for (int row = 0; row < pBitmap->GetHeight(); row++) { | |
uint8_t* scan_line = pBitmap->GetBuffer() + row * pBitmap->GetPitch(); | |
fwrite(scan_line, pBitmap->GetPitch(), 1, file); | |
} | |
fclose(file); | |
} | |
FWL_ERR FWL_WidgetMgrSnapshot(IFWL_Widget* pWidget, | |
const CFX_WideString* saveFile, | |
const CFX_Matrix* pMatrix) { | |
CFX_RectF r; | |
pWidget->GetWidgetRect(r); | |
CFX_Graphics gs; | |
gs.Create((int32_t)r.width, (int32_t)r.height, FXDIB_Argb); | |
CFWL_WidgetMgr* widgetMgr = static_cast<CFWL_WidgetMgr*>(FWL_GetWidgetMgr()); | |
CFWL_WidgetMgrDelegate* delegate = widgetMgr->GetDelegate(); | |
delegate->OnDrawWidget(pWidget, &gs, pMatrix); | |
CFX_DIBitmap* dib = gs.GetRenderDevice()->GetBitmap(); | |
FWL_WriteBMP(dib, saveFile->UTF8Encode()); | |
return FWL_ERR_Succeeded; | |
} | |
FX_BOOL FWL_WidgetIsChild(IFWL_Widget* parent, IFWL_Widget* find) { | |
if (!find) { | |
return FALSE; | |
} | |
IFWL_Widget* child = | |
FWL_GetWidgetMgr()->GetWidget(parent, FWL_WGTRELATION_FirstChild); | |
while (child) { | |
if (child == find) { | |
return TRUE; | |
} | |
if (FWL_WidgetIsChild(child, find)) { | |
return TRUE; | |
} | |
child = FWL_GetWidgetMgr()->GetWidget(child, FWL_WGTRELATION_NextSibling); | |
} | |
return FALSE; | |
} |