From 46bcaeb772844a2dd5e41394aa6a5713743fccf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Tue, 13 Apr 2021 21:14:17 +0800 Subject: [PATCH] add doric layout --- doric-Qt/doric/doric.pro | 2 + doric-Qt/doric/plugin/DoricShaderPlugin.cpp | 2 + doric-Qt/doric/resources/hlayout.qml | 86 +-- doric-Qt/doric/resources/stack.qml | 37 -- doric-Qt/doric/resources/text.qml | 6 +- doric-Qt/doric/resources/vlayout.qml | 87 +-- doric-Qt/doric/shader/DoricGroupNode.cpp | 33 +- doric-Qt/doric/shader/DoricGroupNode.h | 4 + doric-Qt/doric/shader/DoricHLayoutNode.cpp | 10 +- doric-Qt/doric/shader/DoricRootNode.cpp | 8 + doric-Qt/doric/shader/DoricRootNode.h | 2 + doric-Qt/doric/shader/DoricStackNode.cpp | 4 + doric-Qt/doric/shader/DoricSuperNode.cpp | 7 - doric-Qt/doric/shader/DoricSuperNode.h | 2 - doric-Qt/doric/shader/DoricTextNode.cpp | 1 + doric-Qt/doric/shader/DoricVLayoutNode.cpp | 10 +- doric-Qt/doric/shader/DoricViewNode.cpp | 125 ++-- doric-Qt/doric/shader/DoricViewNode.h | 20 +- doric-Qt/doric/utils/DoricLayouts.cpp | 660 ++++++++++++++++++++ doric-Qt/doric/utils/DoricLayouts.h | 166 +++++ 20 files changed, 956 insertions(+), 316 deletions(-) create mode 100644 doric-Qt/doric/utils/DoricLayouts.cpp create mode 100644 doric-Qt/doric/utils/DoricLayouts.h diff --git a/doric-Qt/doric/doric.pro b/doric-Qt/doric/doric.pro index dd6c8422..55150222 100644 --- a/doric-Qt/doric/doric.pro +++ b/doric-Qt/doric/doric.pro @@ -46,6 +46,7 @@ SOURCES += \ shader/DoricViewNode.cpp \ utils/DoricConstant.cpp \ utils/DoricContextHolder.cpp \ + utils/DoricLayouts.cpp \ utils/DoricMouseAreaBridge.cpp \ widget/flex/FlexLayout.cpp \ widget/flex/FlexLayoutConfig.cpp \ @@ -114,6 +115,7 @@ HEADERS += \ utils/DoricConstant.h \ utils/DoricContextHolder.h \ utils/DoricCountDownLatch.h \ + utils/DoricLayouts.h \ utils/DoricMouseAreaBridge.h \ utils/DoricObjectFactory.h \ utils/DoricThreadMode.h \ diff --git a/doric-Qt/doric/plugin/DoricShaderPlugin.cpp b/doric-Qt/doric/plugin/DoricShaderPlugin.cpp index 0e457cfc..6da90c9e 100644 --- a/doric-Qt/doric/plugin/DoricShaderPlugin.cpp +++ b/doric-Qt/doric/plugin/DoricShaderPlugin.cpp @@ -20,10 +20,12 @@ void DoricShaderPlugin::render(QString jsValueString, QString callbackId) { jsValue["type"].toString() == "Root") { rootNode->setId(viewId); rootNode->blend(jsValue["props"]); + rootNode->requestLayout(); } else { DoricViewNode *viewNode = getContext()->targetViewNode(viewId); if (viewNode != nullptr) { viewNode->blend(jsValue["props"]); + viewNode->requestLayout(); } } } catch (...) { diff --git a/doric-Qt/doric/resources/hlayout.qml b/doric-Qt/doric/resources/hlayout.qml index 0eee11f8..d9763c5e 100644 --- a/doric-Qt/doric/resources/hlayout.qml +++ b/doric-Qt/doric/resources/hlayout.qml @@ -3,21 +3,15 @@ import QtQuick.Controls 2.5 import QtQuick.Layouts 1.15 import "util.mjs" as Util -import "gravity.mjs" as Gravity Rectangle { property var wrapper clip: true - property var tag: "HLayout" - property var uuid: Util.uuidv4() - property int widthSpec: 0 - property int heightSpec: 0 - property int childrenRectWidth: childrenRect.width - property int childrenRectHeight: childrenRect.height + property var tag: "HLayout" onWidthChanged: { console.log(tag, uuid + " onWidthChanged: " + this.width) @@ -27,41 +21,6 @@ Rectangle { console.log(tag, uuid + " onHeightChanged: " + this.height) } - onWidthSpecChanged: { - console.log(tag, uuid + " onWidthSpecChanged: " + this.widthSpec) - console.log(tag, uuid + " parent width: " + parent.width) - - if (this.widthSpec === 2) { - this.width = parent.width - children[1].width = parent.width - } - } - - onHeightSpecChanged: { - console.log(tag, uuid + " onHeightSpecChanged: " + this.heightSpec) - console.log(tag, uuid + " parent height: " + parent.height) - - if (this.heightSpec === 2) { - this.height = parent.height - children[1].height = parent.height - } - } - - onChildrenRectChanged: { - console.log(tag, uuid + " widthSpec: " + widthSpec + " heightSpec: " + heightSpec) - console.log(tag, uuid + " onChildrenRectChanged: " + childrenRect) - this.childrenRectWidth = childrenRect.width - this.childrenRectHeight = childrenRect.height - - if (this.widthSpec === 1) { - this.width = childrenRectWidth - } - - if (this.heightSpec === 1) { - this.height = childrenRectHeight - } - } - color: 'transparent' property var backgroundColor @@ -77,47 +36,4 @@ Rectangle { mouseAreaBridge.onClick(wrapper) } } - - RowLayout { - property int gravity: 0 - - spacing: 0 - - Item { - id: head - objectName: "head" - } - - onChildrenChanged: { - console.log(tag, uuid + " gravity: " + gravity) - for (var i = 0;i !== children.length;i++) { - if (children[i] !== head && children[i] !== tail) { - switch(this.gravity) { - case Gravity.enumerate().CENTER_X: - children[i].Layout.alignment = Qt.AlignHCenter - break - case Gravity.enumerate().CENTER: - children[i].Layout.alignment = Qt.AlignCenter - break - } - } - } - - if (parent.widthSpec == 1) { - tail.Layout.fillWidth = false - } else { - if (gravity === Gravity.enumerate().CENTER || gravity === Gravity.enumerate().CENTER_X) { - head.Layout.fillWidth = true - } else { - head.Layout.fillWidth = false - } - tail.Layout.fillWidth = true - } - } - - Item { - id: tail - objectName: "tail" - } - } } diff --git a/doric-Qt/doric/resources/stack.qml b/doric-Qt/doric/resources/stack.qml index a2ce6cd5..7024b38a 100644 --- a/doric-Qt/doric/resources/stack.qml +++ b/doric-Qt/doric/resources/stack.qml @@ -11,11 +11,6 @@ Rectangle { property var uuid: Util.uuidv4() - property int widthSpec: 0 - property int heightSpec: 0 - property int childrenRectWidth: childrenRect.width - property int childrenRectHeight: childrenRect.height - property var tag: "Stack" onWidthChanged: { @@ -26,38 +21,6 @@ Rectangle { console.log(tag, uuid + " onHeightChanged: " + this.height) } - onWidthSpecChanged: { - console.log(tag, uuid + " onWidthSpecChanged: " + this.widthSpec) - console.log(tag, uuid + " parent width: " + parent.width) - if (this.widthSpec === 2) { - this.width = parent.width - } - } - - onHeightSpecChanged: { - console.log(tag, uuid + " onHeightSpecChanged: " + this.heightSpec) - console.log(tag, uuid + " parent height: " + parent.height) - - if (this.heightSpec === 2) { - this.height = parent.height - } - } - - onChildrenRectChanged: { - console.log(tag, uuid + " widthSpec: " + widthSpec + " heightSpec: " + heightSpec) - console.log(tag, uuid + " onChildrenRectChanged: " + childrenRect) - this.childrenRectWidth = childrenRect.width - this.childrenRectHeight = childrenRect.height - - if (this.widthSpec === 1) { - this.width = childrenRectWidth - } - - if (this.heightSpec === 1) { - this.height = childrenRectHeight - } - } - color: 'transparent' property var backgroundColor diff --git a/doric-Qt/doric/resources/text.qml b/doric-Qt/doric/resources/text.qml index 7653359b..2620ca6f 100644 --- a/doric-Qt/doric/resources/text.qml +++ b/doric-Qt/doric/resources/text.qml @@ -39,11 +39,13 @@ TextArea { } onWidthChanged: { - bg.implicitWidth = width +// bg.implicitWidth = width + console.log(tag, uuid + " onWidthChanged: " + this.width) } onHeightChanged: { - bg.implicitHeight = height +// bg.implicitHeight = height + console.log(tag, uuid + " onHeightChanged: " + this.height) } MouseArea { diff --git a/doric-Qt/doric/resources/vlayout.qml b/doric-Qt/doric/resources/vlayout.qml index 8f0cbb1b..b35fe3a1 100644 --- a/doric-Qt/doric/resources/vlayout.qml +++ b/doric-Qt/doric/resources/vlayout.qml @@ -3,21 +3,15 @@ import QtQuick.Controls 2.5 import QtQuick.Layouts 1.15 import "util.mjs" as Util -import "gravity.mjs" as Gravity Rectangle { property var wrapper clip: true - property var tag: "VLayout" - property var uuid: Util.uuidv4() - property int widthSpec: 0 - property int heightSpec: 0 - property int childrenRectWidth: childrenRect.width - property int childrenRectHeight: childrenRect.height + property var tag: "VLayout" onWidthChanged: { console.log(tag, uuid + " onWidthChanged: " + this.width) @@ -27,41 +21,6 @@ Rectangle { console.log(tag, uuid + " onHeightChanged: " + this.height) } - onWidthSpecChanged: { - console.log(tag, uuid + " onWidthSpecChanged: " + this.widthSpec) - console.log(tag, uuid + " parent width: " + parent.width) - - if (this.widthSpec === 2) { - this.width = parent.width - children[1].width = parent.width - } - } - - onHeightSpecChanged: { - console.log(tag, uuid + " onHeightSpecChanged: " + this.heightSpec) - console.log(tag, uuid + " parent height: " + parent.height) - - if (this.heightSpec === 2) { - this.height = parent.height - children[1].height = parent.height - } - } - - onChildrenRectChanged: { - console.log(tag, uuid + " widthSpec: " + widthSpec + " heightSpec: " + heightSpec) - console.log(tag, uuid + " onChildrenRectChanged: " + childrenRect) - this.childrenRectWidth = childrenRect.width - this.childrenRectHeight = childrenRect.height - - if (this.widthSpec === 1) { - this.width = childrenRectWidth - } - - if (this.heightSpec === 1) { - this.height = childrenRectHeight - } - } - color: 'transparent' property var backgroundColor @@ -77,48 +36,4 @@ Rectangle { mouseAreaBridge.onClick(wrapper) } } - - ColumnLayout { - property int gravity: 0 - - spacing: 0 - - Item { - id: head - objectName: "head" - } - - onChildrenChanged: { - console.log(tag, uuid + " gravity: " + gravity) - - for (var i = 0;i !== children.length;i++) { - if (children[i] !== head && children[i] !== tail) { - switch(this.gravity) { - case Gravity.enumerate().CENTER_X: - children[i].Layout.alignment = Qt.AlignHCenter - break - case Gravity.enumerate().CENTER: - children[i].Layout.alignment = Qt.AlignCenter - break - } - } - } - - if (parent.heightSpec == 1) { - tail.Layout.fillHeight = false - } else { - if (gravity === Gravity.enumerate().CENTER || gravity === Gravity.enumerate().CENTER_Y) { - head.Layout.fillHeight = true - } else { - head.Layout.fillHeight = false - } - tail.Layout.fillHeight = true - } - } - - Item { - id: tail - objectName: "tail" - } - } } diff --git a/doric-Qt/doric/shader/DoricGroupNode.cpp b/doric-Qt/doric/shader/DoricGroupNode.cpp index ca4742ca..16504e25 100644 --- a/doric-Qt/doric/shader/DoricGroupNode.cpp +++ b/doric-Qt/doric/shader/DoricGroupNode.cpp @@ -20,16 +20,13 @@ void DoricGroupNode::blend(QQuickItem *view, QString name, QJsonValue prop) { void DoricGroupNode::blend(QJsonValue jsValue) { DoricViewNode::blend(jsValue); - configChildNode(); } +void DoricGroupNode::afterBlended(QJsonValue props) { configChildNode(); } + void DoricGroupNode::configChildNode() { - QQuickItem *parent = nullptr; - if (mType == "HLayout" || mType == "VLayout") { - parent = mView->childItems().at(1); - } else { - parent = mView; - } + QQuickItem *parent = mView; + for (int idx = 0; idx < mChildViewIds.size(); idx++) { QString id = mChildViewIds.at(idx); QJsonValue model = getSubModel(id); @@ -140,23 +137,6 @@ void DoricGroupNode::configChildNode() { viewNode->getNodeView()->setParentItem(nullptr); viewNode->getNodeView()->deleteLater(); } - - // handle tail - if (mType == "VLayout" || mType == "HLayout") { - int tailIndex = -1; - for (int idx = 0; idx < parent->childItems().size(); idx++) { - if (parent->childItems().at(idx)->objectName() == "tail") { - tailIndex = idx; - break; - } - } - if (tailIndex != -1 && tailIndex != parent->childItems().size() - 1) { - QQuickItem *tail = parent->childItems().at(tailIndex); - tail->setParentItem(nullptr); - tail->setParentItem(parent); - } - } - } void DoricGroupNode::blendSubNode(QJsonValue subProperties) { @@ -168,3 +148,8 @@ void DoricGroupNode::blendSubNode(QJsonValue subProperties) { } } } + +void DoricGroupNode::requestLayout() { + DoricSuperNode::requestLayout(); + foreach (DoricViewNode *node, this->mChildNodes) { node->requestLayout(); } +} diff --git a/doric-Qt/doric/shader/DoricGroupNode.h b/doric-Qt/doric/shader/DoricGroupNode.h index 8d37031a..2d4db4de 100644 --- a/doric-Qt/doric/shader/DoricGroupNode.h +++ b/doric-Qt/doric/shader/DoricGroupNode.h @@ -19,6 +19,10 @@ protected: void configChildNode(); virtual void blendSubNode(QJsonValue subProperties) override; + + virtual void afterBlended(QJsonValue props) override; + + virtual void requestLayout() override; }; #endif // DORICGROUPNODE_H diff --git a/doric-Qt/doric/shader/DoricHLayoutNode.cpp b/doric-Qt/doric/shader/DoricHLayoutNode.cpp index 8e0e48c3..864044ab 100644 --- a/doric-Qt/doric/shader/DoricHLayoutNode.cpp +++ b/doric-Qt/doric/shader/DoricHLayoutNode.cpp @@ -11,16 +11,20 @@ QQuickItem *DoricHLayoutNode::build() { } QQuickItem *item = qobject_cast(component.create()); + this->createLayouts(item); + + getLayouts()->setLayoutType(DoricLayoutType::DoricHLayout); + item->setProperty("wrapper", QString::number((qint64)this)); return item; } void DoricHLayoutNode::blend(QQuickItem *view, QString name, QJsonValue prop) { - QQuickItem *container = view->childItems().at(1); + QQuickItem *container = view; if (name == "space") { - container->setProperty("spacing", prop.toInt()); + getLayouts()->setSpacing(prop.toInt()); } else if (name == "gravity") { - container->setProperty("gravity", prop.toInt()); + getLayouts()->setGravity(prop.toInt()); } else { DoricGroupNode::blend(view, name, prop); } diff --git a/doric-Qt/doric/shader/DoricRootNode.cpp b/doric-Qt/doric/shader/DoricRootNode.cpp index dade93c3..9ae17e9f 100644 --- a/doric-Qt/doric/shader/DoricRootNode.cpp +++ b/doric-Qt/doric/shader/DoricRootNode.cpp @@ -2,4 +2,12 @@ void DoricRootNode::setRootView(QQuickItem *rootView) { this->mView = rootView; + this->createLayouts(rootView); + + this->getLayouts()->setLayoutType(DoricLayoutType::DoricStack); +} + +void DoricRootNode::requestLayout() { + getLayouts()->apply(); + DoricStackNode::requestLayout(); } diff --git a/doric-Qt/doric/shader/DoricRootNode.h b/doric-Qt/doric/shader/DoricRootNode.h index 4c577d61..33c91bb5 100644 --- a/doric-Qt/doric/shader/DoricRootNode.h +++ b/doric-Qt/doric/shader/DoricRootNode.h @@ -10,6 +10,8 @@ public: using DoricStackNode::DoricStackNode; void setRootView(QQuickItem *rootView); + + virtual void requestLayout() override; }; #endif // ROOTNODE_H diff --git a/doric-Qt/doric/shader/DoricStackNode.cpp b/doric-Qt/doric/shader/DoricStackNode.cpp index 0432f249..601c2041 100644 --- a/doric-Qt/doric/shader/DoricStackNode.cpp +++ b/doric-Qt/doric/shader/DoricStackNode.cpp @@ -11,6 +11,10 @@ QQuickItem *DoricStackNode::build() { } QQuickItem *item = qobject_cast(component.create()); + this->createLayouts(item); + + getLayouts()->setLayoutType(DoricLayoutType::DoricStack); + item->setProperty("wrapper", QString::number((qint64)this)); return item; } diff --git a/doric-Qt/doric/shader/DoricSuperNode.cpp b/doric-Qt/doric/shader/DoricSuperNode.cpp index 87fb3190..6bf51461 100644 --- a/doric-Qt/doric/shader/DoricSuperNode.cpp +++ b/doric-Qt/doric/shader/DoricSuperNode.cpp @@ -54,10 +54,3 @@ void DoricSuperNode::blendSubLayoutConfig(DoricViewNode *viewNode, QJsonValue jsValue) { viewNode->blendLayoutConfig(jsValue); } - -QJsonValue DoricSuperNode::generateDefaultLayoutConfig() { - QJsonObject layoutConfig; - layoutConfig.insert("widthSpec", SpecMode::JUST); - layoutConfig.insert("heightSpec", SpecMode::JUST); - return layoutConfig; -} diff --git a/doric-Qt/doric/shader/DoricSuperNode.h b/doric-Qt/doric/shader/DoricSuperNode.h index 5f3d7754..42f02ddb 100644 --- a/doric-Qt/doric/shader/DoricSuperNode.h +++ b/doric-Qt/doric/shader/DoricSuperNode.h @@ -23,8 +23,6 @@ public: void blendSubLayoutConfig(DoricViewNode *viewNode, QJsonValue jsValue); - QJsonValue generateDefaultLayoutConfig(); - private: void mixinSubNode(QJsonValue subNode); diff --git a/doric-Qt/doric/shader/DoricTextNode.cpp b/doric-Qt/doric/shader/DoricTextNode.cpp index e7c8ddc6..f578b33d 100644 --- a/doric-Qt/doric/shader/DoricTextNode.cpp +++ b/doric-Qt/doric/shader/DoricTextNode.cpp @@ -12,6 +12,7 @@ QQuickItem *DoricTextNode::build() { } QQuickItem *item = qobject_cast(component.create()); + this->createLayouts(item); item->setProperty("wrapper", QString::number((qint64)this)); return item; diff --git a/doric-Qt/doric/shader/DoricVLayoutNode.cpp b/doric-Qt/doric/shader/DoricVLayoutNode.cpp index 6861cfeb..def27416 100644 --- a/doric-Qt/doric/shader/DoricVLayoutNode.cpp +++ b/doric-Qt/doric/shader/DoricVLayoutNode.cpp @@ -11,16 +11,20 @@ QQuickItem *DoricVLayoutNode::build() { } QQuickItem *item = qobject_cast(component.create()); + this->createLayouts(item); + + getLayouts()->setLayoutType(DoricLayoutType::DoricVLayout); + item->setProperty("wrapper", QString::number((qint64)this)); return item; } void DoricVLayoutNode::blend(QQuickItem *view, QString name, QJsonValue prop) { - QQuickItem *container = view->childItems().at(1); + QQuickItem *container = view; if (name == "space") { - container->setProperty("spacing", prop.toInt()); + getLayouts()->setSpacing(prop.toInt()); } else if (name == "gravity") { - container->setProperty("gravity", prop.toInt()); + getLayouts()->setGravity(prop.toInt()); } else { DoricGroupNode::blend(view, name, prop); } diff --git a/doric-Qt/doric/shader/DoricViewNode.cpp b/doric-Qt/doric/shader/DoricViewNode.cpp index 43b0d214..1ffe83d6 100644 --- a/doric-Qt/doric/shader/DoricViewNode.cpp +++ b/doric-Qt/doric/shader/DoricViewNode.cpp @@ -3,42 +3,62 @@ #include "../utils/DoricUtils.h" #include "DoricSuperNode.h" -void DoricViewNode::blendLayoutConfig(QJsonValue jsObject) { - this->mLayoutConfig = jsObject; +void DoricViewNode::blendLayoutConfig(QJsonValue jsValue) { + QJsonObject jsObject = jsValue.toObject(); + if (jsObject.contains("widthSpec")) + getLayouts()->setWidthSpec(jsObject["widthSpec"].toInt()); - QJsonValue margin = jsObject["margin"]; - QJsonValue widthSpec = jsObject["widthSpec"]; - QJsonValue heightSpec = jsObject["heightSpec"]; + if (jsObject.contains("heightSpec")) + getLayouts()->setHeightSpec(jsObject["heightSpec"].toInt()); - if (widthSpec.isDouble()) { - switch (widthSpec.toInt()) { - case SpecMode::JUST: - mView->setProperty("widthSpec", SpecMode::JUST); - break; - case SpecMode::FIT: - mView->setProperty("widthSpec", SpecMode::FIT); - break; - case SpecMode::MOST: - mView->setProperty("widthSpec", SpecMode::MOST); - break; - } + if (jsObject.contains("margin")) { + QJsonObject margin = jsObject["margin"].toObject(); + + if (margin.contains("left")) + getLayouts()->setMarginLeft(margin["left"].toInt()); + + if (margin.contains("top")) + getLayouts()->setMarginTop(margin["top"].toInt()); + + if (margin.contains("right")) + getLayouts()->setMarginRight(margin["right"].toInt()); + + if (margin.contains("bottom")) + getLayouts()->setMarginBottom(margin["bottom"].toInt()); } - if (heightSpec.isDouble()) { - switch (heightSpec.toInt()) { - case SpecMode::JUST: - mView->setProperty("heightSpec", SpecMode::JUST); - break; - case SpecMode::FIT: - mView->setProperty("heightSpec", SpecMode::FIT); - break; - case SpecMode::MOST: - mView->setProperty("heightSpec", SpecMode::MOST); - break; - } + if (jsObject.contains("alignment")) + getLayouts()->setAlignment(jsObject["alignment"].toInt()); + + if (jsObject.contains("weight")) + getLayouts()->setWeight(jsObject["weight"].toInt()); + + if (jsObject.contains("maxWidth")) + getLayouts()->setMaxWidth(jsObject["maxWidth"].toInt()); + + if (jsObject.contains("maxHeight")) + getLayouts()->setMaxHeight(jsObject["maxHeight"].toInt()); + + if (jsObject.contains("minWidth")) + getLayouts()->setMinWidth(jsObject["minWidth"].toInt()); + + if (jsObject.contains("minHeight")) + getLayouts()->setMinHeight(jsObject["minHeight"].toInt()); +} + +void DoricViewNode::createLayouts(QQuickItem *view) { + if (mLayouts == nullptr) { + mLayouts = new DoricLayouts(); + mLayouts->setWidth(view->width()); + mLayouts->setHeight(view->height()); + mLayouts->setView(view); + + view->setProperty("doricLayout", QString::number((qint64)mLayouts)); } } +DoricLayouts *DoricViewNode::getLayouts() { return mLayouts; } + void DoricViewNode::setLayoutConfig(QJsonValue layoutConfig) { if (mSuperNode != nullptr) { mSuperNode->blendSubLayoutConfig(this, layoutConfig); @@ -53,8 +73,8 @@ void DoricViewNode::init(DoricSuperNode *superNode) { thiz->mReusable = superNode->mReusable; } this->mSuperNode = superNode; - this->mLayoutConfig = superNode->generateDefaultLayoutConfig(); this->mView = build(); + getLayouts(); } QString DoricViewNode::getId() { return mId; } @@ -75,54 +95,41 @@ void DoricViewNode::blend(QJsonValue jsValue) { QJsonValue value = jsValue[key]; blend(mView, key, value); } + + this->afterBlended(jsValue); } void DoricViewNode::blend(QQuickItem *view, QString name, QJsonValue prop) { if (name == "width") { - if (!prop.isDouble()) { - return; - } - if (this->mLayoutConfig.isUndefined()) { - view->setWidth(prop.toInt()); - } else { - QJsonValue widthSpec = this->mLayoutConfig["widthSpec"]; - if (widthSpec.isDouble()) { - if (widthSpec.toInt() == SpecMode::JUST) { - view->setWidth(prop.toInt()); - } - } - } + getLayouts()->setWidth(prop.toInt()); } else if (name == "height") { - if (!prop.isDouble()) { - return; - } - if (this->mLayoutConfig.isUndefined()) { - view->setHeight(prop.toInt()); - } else { - QJsonValue heightSpec = this->mLayoutConfig["heightSpec"]; - if (heightSpec.isDouble()) { - if (heightSpec.toInt() == SpecMode::JUST) { - view->setHeight(prop.toInt()); - } - } - } + getLayouts()->setHeight(prop.toInt()); } else if (name == "backgroundColor") { QString color = DoricUtils::doricColor(prop.toInt()).name(); view->setProperty("backgroundColor", color); } else if (name == "x") { - view->setProperty("x", prop.toInt()); + getLayouts()->setMarginLeft(prop.toInt()); } else if (name == "y") { - view->setProperty("y", prop.toInt()); + getLayouts()->setMarginRight(prop.toInt()); } else if (name == "corners") { view->setProperty("radius", prop.toInt()); } else if (name == "onClick") { if (prop.isString()) clickFunction = prop.toString(); + } else if (name == "padding") { + getLayouts()->setPaddingLeft(prop["left"].toInt()); + getLayouts()->setPaddingRight(prop["right"].toInt()); + getLayouts()->setPaddingTop(prop["top"].toInt()); + getLayouts()->setPaddingBottom(prop["bottom"].toInt()); + } else if (name == "hidden") { + getLayouts()->setDisabled(prop.toBool()); } else if (name != "layoutConfig") { qCritical() << name << ": " << prop.toString(); } } +void DoricViewNode::afterBlended(QJsonValue prop) {} + QList DoricViewNode::getIdList() { QList ids; @@ -135,6 +142,8 @@ QList DoricViewNode::getIdList() { return ids; } +void DoricViewNode::requestLayout() {} + void DoricViewNode::callJSResponse(QString funcId, QVariantList args) { QVariantList nArgs; QList idList = getIdList(); diff --git a/doric-Qt/doric/shader/DoricViewNode.h b/doric-Qt/doric/shader/DoricViewNode.h index 57a6d4f1..fbf75021 100644 --- a/doric-Qt/doric/shader/DoricViewNode.h +++ b/doric-Qt/doric/shader/DoricViewNode.h @@ -6,13 +6,7 @@ #include #include "../utils/DoricContextHolder.h" - -class SpecMode { -public: - const static int JUST = 0; - const static int FIT = 1; - const static int MOST = 2; -}; +#include "../utils/DoricLayouts.h" class DoricSuperNode; @@ -21,17 +15,21 @@ class DoricViewNode : public DoricContextHolder { protected: QQuickItem *mView; + DoricLayouts *mLayouts = nullptr; + DoricSuperNode *mSuperNode = nullptr; virtual QQuickItem *build() = 0; + void createLayouts(QQuickItem *view); + + DoricLayouts *getLayouts(); + void setLayoutConfig(QJsonValue layoutConfig); private: QString mId; - QJsonValue mLayoutConfig; - QList getIdList(); QString clickFunction; @@ -70,8 +68,12 @@ public: virtual void blend(QQuickItem *view, QString name, QJsonValue prop); + virtual void afterBlended(QJsonValue prop); + virtual void blendLayoutConfig(QJsonValue jsObject); + virtual void requestLayout(); + void onClick(); void callJSResponse(QString funcId, QVariantList args); diff --git a/doric-Qt/doric/utils/DoricLayouts.cpp b/doric-Qt/doric/utils/DoricLayouts.cpp new file mode 100644 index 00000000..a25815f1 --- /dev/null +++ b/doric-Qt/doric/utils/DoricLayouts.cpp @@ -0,0 +1,660 @@ +#include "DoricLayouts.h" + +DoricLayouts::DoricLayouts() { + this->widthSpec = DoricLayoutSpec::DoricLayoutJust; + this->heightSpec = DoricLayoutSpec::DoricLayoutJust; + this->maxWidth = 32767; + this->maxHeight = 32767; + this->minWidth = 0; + this->minHeight = 0; +} + +void DoricLayouts::setWidthSpec(int widthSpec) { this->widthSpec = widthSpec; } +void DoricLayouts::setHeightSpec(int heightSpec) { + this->heightSpec = heightSpec; +} + +void DoricLayouts::setAlignment(int alignment) { this->alignment = alignment; } + +void DoricLayouts::setGravity(int gravity) { this->gravity = gravity; } + +void DoricLayouts::setWidth(int width) { this->width = width; } +void DoricLayouts::setHeight(int height) { this->height = height; } + +void DoricLayouts::setSpacing(int spacing) { this->spacing = spacing; } + +void DoricLayouts::setMarginLeft(int marginLeft) { + this->marginLeft = marginLeft; +} +void DoricLayouts::setMarginTop(int marginTop) { this->marginTop = marginTop; } +void DoricLayouts::setMarginRight(int marginRight) { + this->marginRight = marginRight; +} +void DoricLayouts::setMarginBottom(int marginBottom) { + this->marginBottom = marginBottom; +} + +void DoricLayouts::setPaddingLeft(int paddingLeft) { + this->paddingLeft = paddingLeft; +} +void DoricLayouts::setPaddingTop(int paddingTop) { + this->paddingTop = paddingTop; +} +void DoricLayouts::setPaddingRight(int paddingRight) { + this->paddingRight = paddingRight; +} +void DoricLayouts::setPaddingBottom(int paddingBottom) { + this->paddingBottom = paddingBottom; +} + +void DoricLayouts::setWeight(int weight) { this->weight = weight; } + +void DoricLayouts::setView(QQuickItem *view) { + this->view = view; + this->tag = view->property("tag").toString(); +} + +void DoricLayouts::setLayoutType(int layoutType) { + this->layoutType = layoutType; +} + +void DoricLayouts::setDisabled(bool disabled) { this->disabled = disabled; } + +void DoricLayouts::setMaxWidth(int maxWidth) { this->maxWidth = maxWidth; } +void DoricLayouts::setMaxHeight(int maxHeight) { this->maxHeight = maxHeight; } +void DoricLayouts::setMinWidth(int minWidth) { this->minWidth = minWidth; } +void DoricLayouts::setMinHeight(int minHeight) { this->minHeight = minHeight; } + +void DoricLayouts::apply(int targetWidth, int targetHeight) { + this->resolved = false; + + this->measure(targetWidth, targetHeight); + this->setFrame(); + + this->resolved = true; +} + +void DoricLayouts::apply() { + this->apply(this->view->width(), this->view->height()); +} + +void DoricLayouts::measure(int targetWidth, int targetHeight) { + this->measureSelf(targetWidth, targetHeight); + this->layout(); +} + +void DoricLayouts::measureSelf(int targetWidth, int targetHeight) { + // measure width + int width; + if (this->widthSpec == DoricLayoutSpec::DoricLayoutMost) { + QQuickItem *parent = this->view->parentItem(); + DoricLayouts *parentDoricLayout = + (DoricLayouts *)(parent->property("doricLayout").toULongLong()); + if (parentDoricLayout->layoutType == DoricLayoutType::DoricHLayout && + this->weight > 0) { + width = this->measuredWidth = 0; + setMeasuredWidth(); + } else { + width = this->measuredWidth = targetWidth; + setMeasuredWidth(); + } + } else if (this->widthSpec == DoricLayoutSpec::DoricLayoutJust) { + width = this->measuredWidth = this->width; + setMeasuredWidth(); + } else { + width = targetWidth; + } + + // measure height + int height; + if (this->heightSpec == DoricLayoutSpec::DoricLayoutMost) { + QQuickItem *parent = this->view->parentItem(); + DoricLayouts *parentDoricLayout = + (DoricLayouts *)(parent->property("doricLayout").toULongLong()); + if (parentDoricLayout->layoutType == DoricLayoutType::DoricVLayout && + this->weight > 0) { + height = this->measuredHeight = 0; + } else { + height = this->measuredHeight = targetHeight; + } + } else if (this->heightSpec == DoricLayoutSpec::DoricLayoutJust) { + height = this->measuredHeight = this->height; + } else { + height = targetHeight; + } + + // measure content + + this->measureContent(width - this->paddingLeft - this->paddingRight, + height - this->paddingTop - this->paddingBottom); + + if (this->restrainSize()) { + this->measureContent( + this->measuredWidth - this->paddingLeft - this->paddingRight, + this->measuredHeight - this->paddingTop - this->paddingBottom); + } + this->restrainSize(); +} + +void DoricLayouts::measureContent(int targetWidth, int targetHeight) { + switch (this->layoutType) { + case DoricLayoutType::DoricStack: { + this->measureStackContent(targetWidth, targetHeight); + break; + } + case DoricLayoutType::DoricVLayout: { + this->measureVLayoutContent(targetWidth, targetHeight); + break; + } + case DoricLayoutType::DoricHLayout: { + this->measureHLayoutContent(targetWidth, targetHeight); + break; + } + default: { + this->measureUndefinedContent(targetWidth, targetHeight); + break; + } + } + + QQuickItem *parent = this->view->parentItem(); + DoricLayouts *parentDoricLayout = + (DoricLayouts *)(parent->property("doricLayout").toULongLong()); + if (parentDoricLayout != nullptr) { + if (parentDoricLayout->layoutType != DoricLayoutType::DoricUndefined && + parentDoricLayout->widthSpec == DoricLayoutSpec::DoricLayoutFit && + this->widthSpec == DoricLayoutSpec::DoricLayoutMost) { + this->measuredWidth = 0; + setMeasuredWidth(); + } + if (parentDoricLayout->layoutType != DoricLayoutType::DoricUndefined && + parentDoricLayout->heightSpec == DoricLayoutSpec::DoricLayoutFit && + this->heightSpec == DoricLayoutSpec::DoricLayoutMost) { + this->measuredHeight = 0; + } + } +} + +void DoricLayouts::measureUndefinedContent(int targetWidth, int targetHeight) { + int width = this->view->width(); + int height = this->view->height(); + + if (width > targetWidth) { + width = targetWidth; + } + if (height > targetHeight) { + height = targetHeight; + } + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredWidth = width + this->paddingLeft + this->paddingRight; + setMeasuredWidth(); + } + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredHeight = height + this->paddingTop + this->paddingBottom; + } +} +void DoricLayouts::measureStackContent(int targetWidth, int targetHeight) { + int contentWidth = 0, contentHeight = 0; + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + + QPair size = layout->removeMargin(targetWidth, targetHeight); + layout->measure(size.first, size.second); + contentWidth = qMax(contentWidth, layout->takenWidth()); + contentHeight = qMax(contentHeight, layout->takenHeight()); + } + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredWidth = contentWidth + this->paddingLeft + this->paddingRight; + setMeasuredWidth(); + } + + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredHeight = + contentHeight + this->paddingTop + this->paddingBottom; + } + + this->contentWidth = contentWidth; + this->contentHeight = contentHeight; +} +void DoricLayouts::measureVLayoutContent(int targetWidth, int targetHeight) { + int contentWidth = 0, contentHeight = 0, contentWeight = 0; + bool had = false; + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + had = true; + + QPair pair = + layout->removeMargin(targetWidth, targetHeight - contentHeight); + layout->measure(pair.first, pair.second); + contentWidth = qMax(contentWidth, layout->takenWidth()); + contentHeight += layout->takenHeight() + this->spacing; + contentWeight += layout->weight; + } + + if (had) { + contentHeight -= this->spacing; + } + + if (contentWeight > 0) { + int remaining = targetHeight - contentHeight; + contentWidth = 0; + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + int measuredHeight = + layout->measuredHeight + remaining / contentWeight * layout->weight; + layout->measuredHeight = measuredHeight; + // Need Remeasure + layout->measureContent( + layout->measuredWidth - layout->paddingLeft - layout->paddingRight, + measuredHeight - layout->paddingTop - layout->paddingBottom); + layout->measuredHeight = measuredHeight; + contentWidth = qMax(contentWidth, layout->takenWidth()); + } + contentHeight = targetHeight; + } + + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredWidth = contentWidth + this->paddingLeft + this->paddingRight; + setMeasuredWidth(); + } + + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredHeight = + contentHeight + this->paddingTop + this->paddingBottom; + } + + this->contentWidth = contentWidth; + this->contentHeight = contentHeight; +} +void DoricLayouts::measureHLayoutContent(int targetWidth, int targetHeight) { + int contentWidth = 0, contentHeight = 0, contentWeight = 0; + bool had = false; + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + had = true; + QPair pair = + layout->removeMargin(targetWidth - contentWidth, targetHeight); + layout->measure(pair.first, pair.second); + contentWidth += layout->takenWidth() + this->spacing; + contentHeight = qMax(contentHeight, layout->takenHeight()); + contentWeight += layout->weight; + } + + if (had) { + contentWidth -= this->spacing; + } + + if (contentWeight > 0) { + int remaining = targetWidth - contentWidth; + contentHeight = 0; + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + int measuredWidth = + layout->measuredWidth + remaining / contentWeight * layout->weight; + layout->measuredWidth = measuredWidth; + // Need Remeasure + layout->measureContent( + measuredWidth - layout->paddingLeft - layout->paddingRight, + layout->measuredHeight - layout->paddingTop - layout->paddingBottom); + layout->measuredWidth = measuredWidth; + contentHeight = qMax(contentHeight, layout->takenHeight()); + } + contentWidth = targetWidth; + } + + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredWidth = contentWidth + this->paddingLeft + this->paddingRight; + setMeasuredWidth(); + } + + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit) { + this->measuredHeight = + contentHeight + this->paddingTop + this->paddingBottom; + } + + this->contentWidth = contentWidth; + this->contentHeight = contentHeight; +} + +int DoricLayouts::takenWidth() { + return this->measuredWidth + this->marginLeft + this->marginRight; +} +int DoricLayouts::takenHeight() { + return this->measuredHeight + this->marginTop + this->marginBottom; +} +QPair DoricLayouts::removeMargin(int targetWidth, int targetHeight) { + QPair pair(targetWidth - this->marginLeft - this->marginRight, + targetHeight - this->marginTop - this->marginBottom); + return pair; +} + +bool DoricLayouts::restrainSize() { + bool needRemeasure = false; + if (this->measuredWidth > this->maxWidth) { + this->measuredWidth = this->maxWidth; + setMeasuredWidth(); + needRemeasure = true; + } + if (this->measuredHeight > this->maxHeight) { + this->measuredHeight = this->maxHeight; + needRemeasure = true; + } + if (this->measuredWidth < this->minWidth) { + this->measuredWidth = this->minWidth; + setMeasuredWidth(); + needRemeasure = true; + } + if (this->measuredHeight < this->minHeight) { + this->measuredHeight = this->minHeight; + needRemeasure = true; + } + return needRemeasure; +} + +void DoricLayouts::layout() { + switch (this->layoutType) { + case DoricLayoutType::DoricStack: { + this->layoutStack(); + break; + } + case DoricLayoutType::DoricVLayout: { + this->layoutVLayout(); + break; + } + case DoricLayoutType::DoricHLayout: { + this->layoutHLayout(); + break; + } + default: { + break; + } + } +} + +void DoricLayouts::setFrame() { + if (this->layoutType != DoricLayoutType::DoricUndefined) { + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + layout->setFrame(); + } + } + + this->view->setProperty("width", this->measuredWidth); + this->view->setProperty("height", this->measuredHeight); + this->view->setProperty("x", this->measuredX); + this->view->setProperty("y", this->measuredY); +} + +void DoricLayouts::layoutStack() { + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit && + layout->widthSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredWidth = + this->measuredWidth - layout->marginLeft - layout->marginRight; + } + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit && + layout->heightSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredHeight = + this->measuredHeight - layout->marginTop - layout->marginBottom; + } + layout->layout(); + + int gravity = layout->alignment; + if ((gravity & DoricGravity::DoricGravityLeft) == + DoricGravity::DoricGravityLeft) { + layout->measuredX = this->paddingLeft; + } else if ((gravity & DoricGravity::DoricGravityRight) == + DoricGravity::DoricGravityRight) { + layout->measuredX = + this->measuredWidth - this->paddingRight - layout->measuredWidth; + } else if ((gravity & DoricGravity::DoricGravityCenterX) == + DoricGravity::DoricGravityCenterX) { + layout->measuredX = this->measuredWidth / 2 - layout->measuredWidth / 2; + } else { + if (layout->marginLeft || layout->marginRight) { + layout->measuredX = this->paddingLeft; + } else { + layout->measuredX = 0; + } + } + + if ((gravity & DoricGravity::DoricGravityTop) == + DoricGravity::DoricGravityTop) { + layout->measuredY = this->paddingTop; + } else if ((gravity & DoricGravity::DoricGravityBottom) == + DoricGravity::DoricGravityBottom) { + layout->measuredY = + this->measuredHeight - this->paddingBottom - layout->measuredHeight; + } else if ((gravity & DoricGravity::DoricGravityCenterY) == + DoricGravity::DoricGravityCenterY) { + layout->measuredY = this->measuredHeight / 2 - layout->measuredHeight / 2; + } else { + if (layout->marginTop || layout->marginBottom) { + layout->measuredY = this->paddingTop; + } else { + layout->measuredY = 0; + } + } + + if (!gravity) { + gravity = DoricGravity::DoricGravityLeft | DoricGravity::DoricGravityTop; + } + if (layout->marginLeft && !((gravity & DoricGravity::DoricGravityRight) == + DoricGravity::DoricGravityRight)) { + layout->measuredX += layout->marginLeft; + } + if (layout->marginRight && !((gravity & DoricGravity::DoricGravityLeft) == + DoricGravity::DoricGravityLeft)) { + layout->measuredX -= layout->marginRight; + } + if (layout->marginTop && !((gravity & DoricGravity::DoricGravityBottom) == + DoricGravity::DoricGravityBottom)) { + layout->measuredY += layout->marginTop; + } + if (layout->marginBottom && !((gravity & DoricGravity::DoricGravityTop) == + DoricGravity::DoricGravityTop)) { + layout->measuredY -= layout->marginBottom; + } + } +} + +void DoricLayouts::layoutVLayout() { + int yStart = this->paddingTop; + if ((this->gravity & DoricGravity::DoricGravityTop) == + DoricGravity::DoricGravityTop) { + yStart = this->paddingTop; + } else if ((this->gravity & DoricGravity::DoricGravityBottom) == + DoricGravity::DoricGravityBottom) { + yStart = this->measuredHeight - this->contentHeight - this->paddingBottom; + } else if ((this->gravity & DoricGravity::DoricGravityCenterY) == + DoricGravity::DoricGravityCenterY) { + yStart = (this->measuredHeight - this->contentHeight - this->paddingTop - + this->paddingBottom) / + 2 + + this->paddingTop; + } + + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit && + layout->widthSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredWidth = + this->measuredWidth - layout->marginLeft - layout->marginRight; + } + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit && + layout->heightSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredHeight = this->measuredHeight - yStart - + layout->marginTop - layout->marginBottom; + } + layout->layout(); + int gravity = layout->alignment | this->gravity; + if ((gravity & DoricGravity::DoricGravityLeft) == + DoricGravity::DoricGravityLeft) { + layout->measuredX = this->paddingLeft; + } else if ((gravity & DoricGravity::DoricGravityRight) == + DoricGravity::DoricGravityRight) { + layout->measuredX = + this->measuredWidth - this->paddingRight - layout->measuredWidth; + } else if ((gravity & DoricGravity::DoricGravityCenterX) == + DoricGravity::DoricGravityCenterX) { + layout->measuredX = this->measuredWidth / 2 - layout->measuredWidth / 2; + } else { + layout->measuredX = this->paddingLeft; + } + if (!gravity) { + gravity = DoricGravity::DoricGravityLeft; + } + if (layout->marginLeft && !((gravity & DoricGravity::DoricGravityRight) == + DoricGravity::DoricGravityRight)) { + layout->measuredX += layout->marginLeft; + } + if (layout->marginRight && !((gravity & DoricGravity::DoricGravityLeft) == + DoricGravity::DoricGravityLeft)) { + layout->measuredX -= layout->marginRight; + } + layout->measuredY = yStart + layout->marginTop; + yStart += this->spacing + layout->takenHeight(); + } +} + +void DoricLayouts::layoutHLayout() { + int xStart = this->paddingLeft; + if ((this->gravity & DoricGravity::DoricGravityLeft) == + DoricGravity::DoricGravityLeft) { + xStart = this->paddingLeft; + } else if ((this->gravity & DoricGravity::DoricGravityRight) == + DoricGravity::DoricGravityRight) { + xStart = this->measuredWidth - this->contentWidth - this->paddingRight; + } else if ((this->gravity & DoricGravity::DoricGravityCenterX) == + DoricGravity::DoricGravityCenterX) { + xStart = (this->measuredWidth - this->contentWidth - this->paddingLeft - + this->paddingRight) / + 2 + + this->paddingLeft; + } + foreach (QQuickItem *subview, this->view->childItems()) { + DoricLayouts *layout = + (DoricLayouts *)(subview->property("doricLayout").toULongLong()); + if (layout == nullptr) { + continue; + } + + if (layout->disabled) { + continue; + } + + if (this->widthSpec == DoricLayoutSpec::DoricLayoutFit && + layout->widthSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredWidth = this->measuredWidth - xStart - + layout->marginLeft - layout->marginRight; + } + + if (this->heightSpec == DoricLayoutSpec::DoricLayoutFit && + layout->heightSpec == DoricLayoutSpec::DoricLayoutMost) { + layout->measuredHeight = + this->measuredHeight - layout->marginTop - layout->marginBottom; + } + + layout->layout(); + + int gravity = layout->alignment | this->gravity; + if ((gravity & DoricGravity::DoricGravityTop) == + DoricGravity::DoricGravityTop) { + layout->measuredY = this->paddingTop; + } else if ((gravity & DoricGravity::DoricGravityBottom) == + DoricGravity::DoricGravityBottom) { + layout->measuredY = + this->measuredHeight - this->paddingBottom - layout->measuredHeight; + } else if ((gravity & DoricGravity::DoricGravityCenterY) == + DoricGravity::DoricGravityCenterY) { + layout->measuredY = this->measuredHeight / 2 - layout->measuredHeight / 2; + } else { + layout->measuredY = this->paddingTop; + } + if (!gravity) { + gravity = DoricGravity::DoricGravityTop; + } + if (layout->marginTop && !((gravity & DoricGravity::DoricGravityBottom) == + DoricGravity::DoricGravityBottom)) { + layout->measuredY += layout->marginTop; + } + if (layout->marginBottom && !((gravity & DoricGravity::DoricGravityTop) == + DoricGravity::DoricGravityTop)) { + layout->measuredY -= layout->marginBottom; + } + layout->measuredX = xStart + layout->marginLeft; + xStart += this->spacing + layout->takenWidth(); + } +} + +// Private Section +void DoricLayouts::setMeasuredWidth() { + qCritical() << "DoricLayouts: " << tag << this->view->property("uuid") + << " measuredWidth: " << this->measuredWidth; +} + +void DoricLayouts::setMeasuredHeight() { + qCritical() << "DoricLayouts: " << tag + << " measuredHeight: " << this->measuredHeight; +} diff --git a/doric-Qt/doric/utils/DoricLayouts.h b/doric-Qt/doric/utils/DoricLayouts.h new file mode 100644 index 00000000..da91d56f --- /dev/null +++ b/doric-Qt/doric/utils/DoricLayouts.h @@ -0,0 +1,166 @@ +#ifndef DORICLAYOUTS_H +#define DORICLAYOUTS_H + +#include + +class DoricLayoutType { +public: + const static int DoricUndefined = 0; + const static int DoricStack = 1; + const static int DoricVLayout = 2; + const static int DoricHLayout = 3; +}; + +class DoricLayoutSpec { +public: + const static int DoricLayoutJust = 0; + const static int DoricLayoutFit = 1; + const static int DoricLayoutMost = 2; +}; + +class DoricGravity { +public: + const static int DoricGravitySpecified = 1; + const static int DoricGravityStart = 1 << 1; + const static int DoricGravityEnd = 1 << 2; + const static int DoricGravityShiftX = 0; + const static int DoricGravityShiftY = 4; + const static int DoricGravityLeft = + (DoricGravityStart | DoricGravitySpecified) << DoricGravityShiftX; + const static int DoricGravityRight = (DoricGravityEnd | DoricGravitySpecified) + << DoricGravityShiftX; + const static int DoricGravityTop = (DoricGravityStart | DoricGravitySpecified) + << DoricGravityShiftY; + const static int DoricGravityBottom = + (DoricGravityEnd | DoricGravitySpecified) << DoricGravityShiftY; + const static int DoricGravityCenterX = DoricGravitySpecified + << DoricGravityShiftX; + const static int DoricGravityCenterY = DoricGravitySpecified + << DoricGravityShiftY; + const static int DoricGravityCenter = + DoricGravityCenterX | DoricGravityCenterY; +}; + +class DoricLayouts { +public: + DoricLayouts(); + + void setWidthSpec(int widthSpec); + void setHeightSpec(int heightSpec); + + void setAlignment(int alignment); + + void setGravity(int gravity); + + void setWidth(int width); + void setHeight(int height); + + void setSpacing(int spacing); + + void setMarginLeft(int marginLeft); + void setMarginTop(int marginTop); + void setMarginRight(int marginRight); + void setMarginBottom(int marginBottom); + + void setPaddingLeft(int paddingLeft); + void setPaddingTop(int paddingTop); + void setPaddingRight(int paddingRight); + void setPaddingBottom(int paddingBottom); + + void setWeight(int weight); + + void setView(QQuickItem *view); + + void setLayoutType(int layoutType); + + void setDisabled(bool disabled); + + void setMaxWidth(int maxWidth); + void setMaxHeight(int maxHeight); + void setMinWidth(int minWidth); + void setMinHeight(int minHeight); + + void apply(int targetWidth, int targetHeight); + + void apply(); + + void measure(int targetWidth, int targetHeight); + + void measureSelf(int targetWidth, int targetHeight); + + void measureContent(int targetWidth, int targetHeight); + + void measureUndefinedContent(int targetWidth, int targetHeight); + void measureStackContent(int targetWidth, int targetHeight); + void measureVLayoutContent(int targetWidth, int targetHeight); + void measureHLayoutContent(int targetWidth, int targetHeight); + + int takenWidth(); + int takenHeight(); + QPair removeMargin(int targetWidth, int targetHeight); + + bool restrainSize(); + + void layout(); + + void layoutStack(); + void layoutVLayout(); + void layoutHLayout(); + + void setFrame(); + +private: + QString tag; + + int widthSpec; + int heightSpec; + + int alignment; + + int gravity; + + int width; + int height; + + int spacing; + + int marginLeft; + int marginTop; + int marginRight; + int marginBottom; + + int paddingLeft; + int paddingTop; + int paddingRight; + int paddingBottom; + + int weight; + + QQuickItem *view; + + int layoutType; + + bool disabled; + + int maxWidth; + int maxHeight; + int minWidth; + int minHeight; + + bool resolved; + + int measuredWidth; + void setMeasuredWidth(); + int measuredHeight; + void setMeasuredHeight(); + int measuredX; + int measuredY; + + bool undefined; + + // + int contentWidth; + int contentHeight; +}; + +#endif // DORICLAYOUTS_H