244 lines
7.3 KiB
C++
244 lines
7.3 KiB
C++
// Copyright 2014 The PDFium Authors
|
|
// 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 "build/build_config.h"
|
|
#include "fxjs/gc/container_trace.h"
|
|
#include "third_party/base/check.h"
|
|
#include "xfa/fwl/cfwl_app.h"
|
|
#include "xfa/fwl/cfwl_message.h"
|
|
#include "xfa/fwl/cfwl_notedriver.h"
|
|
#include "xfa/fwl/cfwl_pushbutton.h"
|
|
|
|
CFWL_WidgetMgr::CFWL_WidgetMgr(AdapterIface* pAdapter, CFWL_App* pApp)
|
|
: m_pAdapter(pAdapter), m_pApp(pApp) {
|
|
DCHECK(m_pAdapter);
|
|
m_mapWidgetItem[nullptr] = cppgc::MakeGarbageCollected<Item>(
|
|
pApp->GetHeap()->GetAllocationHandle(), nullptr);
|
|
}
|
|
|
|
CFWL_WidgetMgr::~CFWL_WidgetMgr() = default;
|
|
|
|
void CFWL_WidgetMgr::Trace(cppgc::Visitor* visitor) const {
|
|
visitor->Trace(m_pApp);
|
|
visitor->Trace(m_pAdapter);
|
|
ContainerTrace(visitor, m_mapWidgetItem);
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetParentWidget(const CFWL_Widget* pWidget) const {
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return nullptr;
|
|
|
|
Item* pParent = pItem->GetParent();
|
|
return pParent ? pParent->pWidget : nullptr;
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetPriorSiblingWidget(CFWL_Widget* pWidget) const {
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return nullptr;
|
|
|
|
Item* pSibling = pItem->GetPrevSibling();
|
|
return pSibling ? pSibling->pWidget : nullptr;
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetNextSiblingWidget(CFWL_Widget* pWidget) const {
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return nullptr;
|
|
|
|
Item* pSibling = pItem->GetNextSibling();
|
|
return pSibling ? pSibling->pWidget : nullptr;
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetFirstChildWidget(CFWL_Widget* pWidget) const {
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return nullptr;
|
|
|
|
Item* pChild = pItem->GetFirstChild();
|
|
return pChild ? pChild->pWidget : nullptr;
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetLastChildWidget(CFWL_Widget* pWidget) const {
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return nullptr;
|
|
|
|
Item* pChild = pItem->GetLastChild();
|
|
return pChild ? pChild->pWidget : nullptr;
|
|
}
|
|
|
|
void CFWL_WidgetMgr::RepaintWidget(CFWL_Widget* pWidget,
|
|
const CFX_RectF& rect) {
|
|
CFWL_Widget* pNative = pWidget;
|
|
CFX_RectF transformedRect = rect;
|
|
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();
|
|
}
|
|
m_pAdapter->RepaintWidget(pNative);
|
|
}
|
|
|
|
void CFWL_WidgetMgr::InsertWidget(CFWL_Widget* pParent, CFWL_Widget* pChild) {
|
|
Item* pParentItem = GetWidgetMgrItem(pParent);
|
|
if (!pParentItem) {
|
|
pParentItem = CreateWidgetMgrItem(pParent);
|
|
GetWidgetMgrRootItem()->AppendLastChild(pParentItem);
|
|
}
|
|
Item* pChildItem = GetWidgetMgrItem(pChild);
|
|
if (!pChildItem)
|
|
pChildItem = CreateWidgetMgrItem(pChild);
|
|
pParentItem->AppendLastChild(pChildItem);
|
|
}
|
|
|
|
void CFWL_WidgetMgr::RemoveWidget(CFWL_Widget* pWidget) {
|
|
DCHECK(pWidget);
|
|
Item* pItem = GetWidgetMgrItem(pWidget);
|
|
if (!pItem)
|
|
return;
|
|
|
|
while (pItem->GetFirstChild())
|
|
RemoveWidget(pItem->GetFirstChild()->pWidget);
|
|
|
|
pItem->RemoveSelfIfParented();
|
|
m_mapWidgetItem.erase(pWidget);
|
|
}
|
|
|
|
CFWL_Widget* CFWL_WidgetMgr::GetWidgetAtPoint(CFWL_Widget* parent,
|
|
const CFX_PointF& point) const {
|
|
if (!parent)
|
|
return nullptr;
|
|
|
|
CFWL_Widget* child = GetLastChildWidget(parent);
|
|
while (child) {
|
|
if (child->IsVisible()) {
|
|
CFX_PointF pos = parent->GetMatrix().GetInverse().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::GetDefaultButton(CFWL_Widget* pParent) const {
|
|
if (pParent->GetClassID() == FWL_Type::PushButton &&
|
|
(pParent->GetStates() & FWL_STATE_PSB_Default)) {
|
|
return pParent;
|
|
}
|
|
|
|
CFWL_Widget* child = GetFirstChildWidget(pParent);
|
|
while (child) {
|
|
if (child->GetClassID() == FWL_Type::PushButton &&
|
|
(child->GetStates() & FWL_STATE_PSB_Default)) {
|
|
return child;
|
|
}
|
|
if (CFWL_Widget* find = GetDefaultButton(child))
|
|
return find;
|
|
|
|
child = GetNextSiblingWidget(child);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrRootItem() const {
|
|
return GetWidgetMgrItem(nullptr);
|
|
}
|
|
|
|
CFWL_WidgetMgr::Item* CFWL_WidgetMgr::GetWidgetMgrItem(
|
|
const CFWL_Widget* pWidget) const {
|
|
auto it = m_mapWidgetItem.find(pWidget);
|
|
return it != m_mapWidgetItem.end() ? it->second : nullptr;
|
|
}
|
|
|
|
CFWL_WidgetMgr::Item* CFWL_WidgetMgr::CreateWidgetMgrItem(
|
|
CFWL_Widget* pWidget) {
|
|
auto* pItem = cppgc::MakeGarbageCollected<Item>(
|
|
m_pApp->GetHeap()->GetAllocationHandle(), pWidget);
|
|
m_mapWidgetItem[pWidget] = pItem;
|
|
return pItem;
|
|
}
|
|
|
|
void CFWL_WidgetMgr::GetAdapterPopupPos(CFWL_Widget* pWidget,
|
|
float fMinHeight,
|
|
float fMaxHeight,
|
|
const CFX_RectF& rtAnchor,
|
|
CFX_RectF* pPopupRect) const {
|
|
m_pAdapter->GetPopupPos(pWidget, fMinHeight, fMaxHeight, rtAnchor,
|
|
pPopupRect);
|
|
}
|
|
|
|
void CFWL_WidgetMgr::OnProcessMessageToForm(CFWL_Message* pMessage) {
|
|
CFWL_Widget* pDstWidget = pMessage->GetDstTarget();
|
|
if (!pDstWidget)
|
|
return;
|
|
|
|
CFWL_NoteDriver* pNoteDriver = pDstWidget->GetFWLApp()->GetNoteDriver();
|
|
pNoteDriver->ProcessMessage(pMessage);
|
|
}
|
|
|
|
void CFWL_WidgetMgr::OnDrawWidget(CFWL_Widget* pWidget,
|
|
CFGAS_GEGraphics* pGraphics,
|
|
const CFX_Matrix& matrix) {
|
|
if (!pWidget || !pGraphics)
|
|
return;
|
|
|
|
pWidget->GetDelegate()->OnDrawWidget(pGraphics, matrix);
|
|
|
|
CFX_RectF clipBounds = pGraphics->GetClipRect();
|
|
if (!clipBounds.IsEmpty())
|
|
DrawChildren(pWidget, clipBounds, pGraphics, matrix);
|
|
}
|
|
|
|
void CFWL_WidgetMgr::DrawChildren(CFWL_Widget* parent,
|
|
const CFX_RectF& rtClip,
|
|
CFGAS_GEGraphics* pGraphics,
|
|
const CFX_Matrix& mtMatrix) {
|
|
if (!parent)
|
|
return;
|
|
|
|
CFWL_Widget* pNextChild = GetFirstChildWidget(parent);
|
|
while (pNextChild) {
|
|
CFWL_Widget* child = pNextChild;
|
|
pNextChild = GetNextSiblingWidget(child);
|
|
if (!child->IsVisible())
|
|
continue;
|
|
|
|
CFX_RectF rtWidget = child->GetWidgetRect();
|
|
if (rtWidget.IsEmpty())
|
|
continue;
|
|
|
|
CFX_Matrix widgetMatrix;
|
|
CFX_RectF clipBounds(rtWidget);
|
|
widgetMatrix.Concat(mtMatrix);
|
|
widgetMatrix.TranslatePrepend(rtWidget.left, rtWidget.top);
|
|
|
|
if (IFWL_WidgetDelegate* pDelegate = child->GetDelegate())
|
|
pDelegate->OnDrawWidget(pGraphics, widgetMatrix);
|
|
|
|
DrawChildren(child, clipBounds, pGraphics, widgetMatrix);
|
|
}
|
|
}
|
|
|
|
CFWL_WidgetMgr::Item::Item(CFWL_Widget* widget) : pWidget(widget) {}
|
|
|
|
CFWL_WidgetMgr::Item::~Item() = default;
|
|
|
|
void CFWL_WidgetMgr::Item::Trace(cppgc::Visitor* visitor) const {
|
|
GCedTreeNode<Item>::Trace(visitor);
|
|
visitor->Trace(pWidget);
|
|
}
|