From c0ce3b3ae96a11f632d9d68fc663cf0be913645f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Thu, 22 Apr 2021 20:46:00 +0800 Subject: [PATCH] add popover & head nodes --- doric-Qt/doric/DoricContext.cpp | 29 +++++ doric-Qt/doric/DoricContext.h | 10 ++ doric-Qt/doric/DoricRegistry.cpp | 2 + doric-Qt/doric/doric.pro | 2 + doric-Qt/doric/plugin/DoricPopoverPlugin.cpp | 117 +++++++++++++++++++ doric-Qt/doric/plugin/DoricPopoverPlugin.h | 27 +++++ 6 files changed, 187 insertions(+) create mode 100644 doric-Qt/doric/plugin/DoricPopoverPlugin.cpp create mode 100644 doric-Qt/doric/plugin/DoricPopoverPlugin.h diff --git a/doric-Qt/doric/DoricContext.cpp b/doric-Qt/doric/DoricContext.cpp index 244c909b..f8ecb4dc 100644 --- a/doric-Qt/doric/DoricContext.cpp +++ b/doric-Qt/doric/DoricContext.cpp @@ -92,3 +92,32 @@ DoricViewNode *DoricContext::targetViewNode(QString id) { } QString DoricContext::getContextId() { return mContextId; } + +QList DoricContext::allHeadNodes(QString type) { + return mHeadNodes[type].values(); +} + +void DoricContext::addHeadNode(QString type, DoricViewNode *viewNode) { + if (mHeadNodes.contains(type)) { + QMap map = mHeadNodes[type]; + map.insert(viewNode->getId(), viewNode); + } else { + QMap map; + map.insert(viewNode->getId(), viewNode); + mHeadNodes.insert(type, map); + } +} + +void DoricContext::removeHeadNode(QString type, DoricViewNode *viewNode) { + if (mHeadNodes.contains(type)) { + QMap map = mHeadNodes[type]; + map.remove(viewNode->getId()); + } +} + +void DoricContext::clearHeadNodes(QString type) { + if (mHeadNodes.contains(type)) { + QMap map = mHeadNodes[type]; + map.clear(); + } +} diff --git a/doric-Qt/doric/DoricContext.h b/doric-Qt/doric/DoricContext.h index feccb8c5..b8581d53 100644 --- a/doric-Qt/doric/DoricContext.h +++ b/doric-Qt/doric/DoricContext.h @@ -21,6 +21,8 @@ private: DoricInterfaceDriver *driver = NULL; QQmlEngine *mQmlEngine; + QMap> mHeadNodes; + public: DoricContext(QString contextId, QString source, QString extra); @@ -47,6 +49,14 @@ public: DoricViewNode *targetViewNode(QString id); QString getContextId(); + + QList allHeadNodes(QString type); + + void addHeadNode(QString type, DoricViewNode *viewNode); + + void removeHeadNode(QString type, DoricViewNode *viewNode); + + void clearHeadNodes(QString type); }; #endif // CONTEXT_H diff --git a/doric-Qt/doric/DoricRegistry.cpp b/doric-Qt/doric/DoricRegistry.cpp index 0c77d73d..bdccbc23 100644 --- a/doric-Qt/doric/DoricRegistry.cpp +++ b/doric-Qt/doric/DoricRegistry.cpp @@ -1,6 +1,7 @@ #include "DoricRegistry.h" #include "plugin/DoricModalPlugin.h" +#include "plugin/DoricPopoverPlugin.h" #include "plugin/DoricShaderPlugin.h" #include "shader/DoricHLayoutNode.h" @@ -13,6 +14,7 @@ DoricRegistry::DoricRegistry() { registerNativePlugin("shader"); registerNativePlugin("modal"); + registerNativePlugin("popover"); registerViewNode("Root"); registerViewNode("Stack"); diff --git a/doric-Qt/doric/doric.pro b/doric-Qt/doric/doric.pro index 9828149a..e208771d 100644 --- a/doric-Qt/doric/doric.pro +++ b/doric-Qt/doric/doric.pro @@ -35,6 +35,7 @@ SOURCES += \ engine/v8/V8Executor.cpp \ main.cpp \ plugin/DoricModalPlugin.cpp \ + plugin/DoricPopoverPlugin.cpp \ plugin/DoricShaderPlugin.cpp \ shader/DoricGroupNode.cpp \ shader/DoricHLayoutNode.cpp \ @@ -105,6 +106,7 @@ HEADERS += \ engine/v8/V8Executor.h \ plugin/DoricModalPlugin.h \ plugin/DoricNativePlugin.h \ + plugin/DoricPopoverPlugin.h \ plugin/DoricShaderPlugin.h \ shader/DoricGroupNode.h \ shader/DoricHLayoutNode.h \ diff --git a/doric-Qt/doric/plugin/DoricPopoverPlugin.cpp b/doric-Qt/doric/plugin/DoricPopoverPlugin.cpp new file mode 100644 index 00000000..7f3fe2c6 --- /dev/null +++ b/doric-Qt/doric/plugin/DoricPopoverPlugin.cpp @@ -0,0 +1,117 @@ +#include "DoricPopoverPlugin.h" +#include "engine/DoricPromise.h" +#include "shader/DoricRootNode.h" +#include "shader/DoricViewNode.h" + +#include +#include +#include + +void DoricPopoverPlugin::show(QString jsValueString, QString callbackId) { + getContext()->getDriver()->asyncCall( + [this, jsValueString, callbackId] { + QJsonDocument document = + QJsonDocument::fromJson(jsValueString.toUtf8()); + QJsonValue jsValue = document.object(); + + QQuickItem *rootItem = + getContext()->getRootNode()->getRootView()->window()->contentItem(); + + if (this->fullScreenView == nullptr) { + QQmlComponent component(getContext()->getQmlEngine()); + + const QUrl url(QStringLiteral("qrc:/doric/qml/stack.qml")); + component.loadUrl(url); + + if (component.isError()) { + qCritical() << component.errorString(); + } + + QQuickItem *item = qobject_cast(component.create()); + item->setWidth(rootItem->width()); + item->setHeight(rootItem->height()); + + DoricLayouts *layout = new DoricLayouts(); + layout->setWidth(item->width()); + layout->setHeight(item->height()); + layout->setView(item); + layout->setLayoutType(DoricLayoutType::DoricStack); + + item->setProperty("doricLayout", QString::number((qint64)layout)); + + item->setParentItem(rootItem); + + this->fullScreenView = item; + } else { + DoricLayouts *layout = + (DoricLayouts *)(this->fullScreenView->property("doricLayout") + .toULongLong()); + layout->setWidth(rootItem->width()); + layout->setHeight(rootItem->height()); + } + this->fullScreenView->setVisible(true); + + QString viewId = jsValue["id"].toString(); + QString type = jsValue["type"].toString(); + + DoricViewNode *viewNode = getContext()->targetViewNode(viewId); + if (viewNode == nullptr) { + viewNode = DoricViewNode::create(getContext(), type); + viewNode->setId(viewId); + viewNode->init(nullptr); + + viewNode->getNodeView()->setParentItem(this->fullScreenView); + } + + viewNode->blend(jsValue["props"]); + + DoricLayouts *layout = + (DoricLayouts *)(this->fullScreenView->property("doricLayout") + .toULongLong()); + layout->apply(); + + getContext()->addHeadNode(TYPE, viewNode); + + QVariantList args; + DoricPromise::resolve(getContext(), callbackId, args); + }, + DoricThreadMode::UI); +} + +void DoricPopoverPlugin::dismiss(QString jsValueString, QString callbackId) { + getContext()->getDriver()->asyncCall( + [this, jsValueString] { + QJsonDocument document = + QJsonDocument::fromJson(jsValueString.toUtf8()); + QJsonValue jsValue = document.object(); + + if (jsValue.toObject().contains("id")) { + QString viewId = jsValue["id"].toString(); + + DoricViewNode *viewNode = getContext()->targetViewNode(viewId); + this->dismissViewNode(viewNode); + } else { + this->dismissPopover(); + } + }, + DoricThreadMode::UI); +} + +void DoricPopoverPlugin::dismissViewNode(DoricViewNode *viewNode) { + if (viewNode != nullptr) { + getContext()->removeHeadNode(TYPE, viewNode); + viewNode->getNodeView()->setParent(nullptr); + viewNode->getNodeView()->setParentItem(nullptr); + viewNode->getNodeView()->deleteLater(); + } + + if (getContext()->allHeadNodes(TYPE).size() == 0) { + this->fullScreenView->setVisible(false); + } +} + +void DoricPopoverPlugin::dismissPopover() { + foreach (DoricViewNode *node, getContext()->allHeadNodes(TYPE)) { + dismissViewNode(node); + } +} diff --git a/doric-Qt/doric/plugin/DoricPopoverPlugin.h b/doric-Qt/doric/plugin/DoricPopoverPlugin.h new file mode 100644 index 00000000..24ef0d14 --- /dev/null +++ b/doric-Qt/doric/plugin/DoricPopoverPlugin.h @@ -0,0 +1,27 @@ +#ifndef DORICPOPOVERPLUGIN_H +#define DORICPOPOVERPLUGIN_H + +#include "DoricNativePlugin.h" + +#include + +static QString TYPE = "popover"; + +class DoricPopoverPlugin : public DoricNativePlugin { + Q_OBJECT +public: + using DoricNativePlugin::DoricNativePlugin; + + Q_INVOKABLE void show(QString jsValueString, QString callbackId); + + Q_INVOKABLE void dismiss(QString jsValueString, QString callbackId); + +private: + QQuickItem *fullScreenView = nullptr; + + void dismissViewNode(DoricViewNode *node); + + void dismissPopover(); +}; + +#endif // DORICPOPOVERPLUGIN_H