From 06f47e31cc5375bd95eebea9dec6d944284fbc73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Mon, 1 Mar 2021 16:24:40 +0800 Subject: [PATCH] add flex layout, config & service --- doric-Qt/doric/DoricRegistry.cpp | 4 + doric-Qt/doric/doric.pro | 6 + doric-Qt/doric/doric.pro.user | 2 +- doric-Qt/doric/qml.qrc | 1 + doric-Qt/doric/resources/Flex.qml | 312 ++++++++++++++++ doric-Qt/doric/resources/hlayout.qml | 19 +- doric-Qt/doric/widget/flex/FlexLayout.cpp | 341 ++++++++++++++++++ doric-Qt/doric/widget/flex/FlexLayout.h | 141 ++++++++ .../doric/widget/flex/FlexLayoutConfig.cpp | 9 + doric-Qt/doric/widget/flex/FlexLayoutConfig.h | 20 + .../doric/widget/flex/FlexLayoutService.cpp | 35 ++ .../doric/widget/flex/FlexLayoutService.h | 29 ++ 12 files changed, 917 insertions(+), 2 deletions(-) create mode 100644 doric-Qt/doric/resources/Flex.qml create mode 100644 doric-Qt/doric/widget/flex/FlexLayout.cpp create mode 100644 doric-Qt/doric/widget/flex/FlexLayout.h create mode 100644 doric-Qt/doric/widget/flex/FlexLayoutConfig.cpp create mode 100644 doric-Qt/doric/widget/flex/FlexLayoutConfig.h create mode 100644 doric-Qt/doric/widget/flex/FlexLayoutService.cpp create mode 100644 doric-Qt/doric/widget/flex/FlexLayoutService.h diff --git a/doric-Qt/doric/DoricRegistry.cpp b/doric-Qt/doric/DoricRegistry.cpp index e4420f08..e22e620b 100644 --- a/doric-Qt/doric/DoricRegistry.cpp +++ b/doric-Qt/doric/DoricRegistry.cpp @@ -6,8 +6,12 @@ #include "shader/DoricStackNode.h" #include "shader/DoricTextNode.h" #include "shader/DoricVLayoutNode.h" +#include "widget/flex/FlexLayoutService.h" DoricRegistry::DoricRegistry() { + qmlRegisterType("pub.doric.widget", 1, 0, + "FlexLayoutService"); + registerNativePlugin("shader"); registerViewNode("Root"); diff --git a/doric-Qt/doric/doric.pro b/doric-Qt/doric/doric.pro index a1c86e8b..a18e77e8 100644 --- a/doric-Qt/doric/doric.pro +++ b/doric-Qt/doric/doric.pro @@ -41,6 +41,9 @@ SOURCES += \ shader/DoricViewNode.cpp \ utils/DoricConstant.cpp \ utils/DoricContextHolder.cpp \ + widget/flex/FlexLayout.cpp \ + widget/flex/FlexLayoutConfig.cpp \ + widget/flex/FlexLayoutService.cpp \ yoga/Utils.cpp \ yoga/YGConfig.cpp \ yoga/YGEnums.cpp \ @@ -104,6 +107,9 @@ HEADERS += \ utils/DoricObjectFactory.h \ utils/DoricThreadMode.h \ utils/DoricUtils.h \ + widget/flex/FlexLayout.h \ + widget/flex/FlexLayoutConfig.h \ + widget/flex/FlexLayoutService.h \ yoga/Bitfield.h \ yoga/CompactValue.h \ yoga/Utils.h \ diff --git a/doric-Qt/doric/doric.pro.user b/doric-Qt/doric/doric.pro.user index c3506cae..b16dc97b 100644 --- a/doric-Qt/doric/doric.pro.user +++ b/doric-Qt/doric/doric.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/doric-Qt/doric/qml.qrc b/doric-Qt/doric/qml.qrc index 78b0a96e..a2a7c05c 100644 --- a/doric-Qt/doric/qml.qrc +++ b/doric-Qt/doric/qml.qrc @@ -14,6 +14,7 @@ ../../doric-demo/bundle/src/Snake.es5.js + ./resources/Flex.qml ./resources/view.qml ./resources/panel.qml ./resources/stack.qml diff --git a/doric-Qt/doric/resources/Flex.qml b/doric-Qt/doric/resources/Flex.qml new file mode 100644 index 00000000..d65e5c86 --- /dev/null +++ b/doric-Qt/doric/resources/Flex.qml @@ -0,0 +1,312 @@ +import QtQuick 2.10 +import QtQuick.Layouts 1.1 +import pub.doric.widget 1.0 + +Item { + id: flex + + property int minHeight: 0 + property int minWidth: 0 + + property int flexShrink: 0 + property int flexGrow: 0 + + property int marginTop: 0 + property int marginLeft: 0 + property int marginRight: 0 + property int marginBottom: 0 + + property int paddingTop: 0 + property int paddingLeft: 0 + property int paddingRight: 0 + property int paddingBottom: 0 + + property string alignContent: "auto" + property string alignItems: "auto" + property string alignSelf: "auto" + + property string justifyContent: "spaceBetween" + + property string display: "flex" + + property string flexWrap: "noWrap" + + property string flexDirection: "row" + + FlexLayoutService { + id: flexLayoutService + } + + function isFlex(child) { + if (typeof child.flexShrink === 'undefined') { + return false; + } else if (typeof child.flexGrow === 'undefined') { + return false; + } else if (typeof child.minHeight === 'undefined') { + return false; + } else if (typeof child.minWidth === 'undefined') { + return false; + } else if (typeof child.marginTop === 'undefined') { + return false; + } else if (typeof child.marginLeft === 'undefined') { + return false; + } else if (typeof child.marginRight === 'undefined') { + return false; + } else if (typeof child.marginBottom === 'undefined') { + return false; + } else if (typeof child.paddingTop === 'undefined') { + return false; + } else if (typeof child.paddingLeft === 'undefined') { + return false; + } else if (typeof child.paddingRight === 'undefined') { + return false; + } else if (typeof child.paddingBottom === 'undefined') { + return false; + } else if (typeof child.alignContent === 'undefined') { + return false; + } else if (typeof child.alignItems === 'undefined') { + return false; + } else if (typeof child.alignSelf === 'undefined') { + return false; + } else if (typeof child.justifyContent === 'undefined') { + return false; + } else if (typeof child.display === 'undefined') { + return false; + } else if (typeof child.flexWrap === 'undefined') { + return false; + } else if (typeof child.flexDirection === 'undefined') { + return false; + } else { + return true; + } + } + + function setAlignContent(child, node) { + var align = child.alignContent; + if (align === "auto") { + node.setAlignContentAuto(); + } else if (align === "flexStart") { + node.setAlignContentFlexStart(); + } else if (align === "center") { + node.setAlignContentCenter(); + } else if (align === "flexEnd") { + node.setAlignContentFlexEnd(); + } else if (align === "stretch") { + node.setAlignContentStretch(); + } else if (align === "baseline") { + node.setAlignContentBaseline(); + } else if (align === "spaceBetween") { + node.setAlignContentSpaceBetween(); + } else if (align === "spaceAround") { + node.setAlignContentSpaceAround(); + } else { + throw "setAlignContent invalid param"; + } + } + + function setAlignItems(child, node) { + var align = child.alignItems; + if (align === "auto") { + node.setAlignItemsAuto(); + } else if (align === "flexStart") { + node.setAlignItemsFlexStart(); + } else if (align === "center") { + node.setAlignItemsCenter(); + } else if (align === "flexEnd") { + node.setAlignItemsFlexEnd(); + } else if (align === "stretch") { + node.setAlignItemsStretch(); + } else if (align === "baseline") { + node.setAlignItemsBaseline(); + } else if (align === "spaceBetween") { + node.setAlignItemsSpaceBetween(); + } else if (align === "spaceAround") { + node.setAlignItemsSpaceAround(); + } else { + throw "setAlignItems invalid param"; + } + } + + function setAlignSelf(child, node) { + var align = child.alignSelf; + if (align === "auto") { + node.setAlignSelfAuto(); + } else if (align === "flexStart") { + node.setAlignSelfFlexStart(); + } else if (align === "center") { + node.setAlignSelfCenter(); + } else if (align === "flexEnd") { + node.setAlignSelfFlexEnd(); + } else if (align === "stretch") { + node.setAlignSelfStretch(); + } else if (align === "baseline") { + node.setAlignSelfBaseline(); + } else if (align === "spaceBetween") { + node.setAlignSelfSpaceBetween(); + } else if (align === "spaceAround") { + node.setAlignSelfSpaceAround(); + } else { + throw "setAlignSelf invalid param"; + } + } + + function setDisplay(child, node) { + var display = child.display; + if (display === "flex") { + node.setDisplayFlex(); + } else if (display === "none") { + node.setDisplayNone(); + } else { + throw "setDisplay invalid param"; + } + } + + function setJustifyContent(child, node) { + var justify = child.justifyContent; + if (justify === "center") { + node.setJustifyCenter(); + } else if (justify === "flexEnd") { + node.setJustifyFlexEnd(); + } else if (justify === "flexStart") { + node.setJustifyFlexStart(); + } else if (justify === "spaceAround") { + node.setJustifySpaceAround(); + } else if (justify === "spaceEvenly") { + node.setJustifySpaceEvenly(); + } else if (justify === "spaceBetween") { + node.setJustifySpaceBetween(); + } else { + throw "setJustifyContent invalid param"; + } + } + + function setFlexWrap(child, node) { + var wrap = child.flexWrap; + if (wrap === "wrap") { + node.setWrap(); + } else if (wrap === "noWrap") { + node.setNoWrap(); + } else if (wrap === "wrapReverse") { + node.setWrapReverse(); + } else { + throw "setFlexWrap invalid param"; + } + } + + function setFlexDirection(child, node) { + var direction = child.flexDirection; + if (direction === "row") { + node.setFlexDirectionRow(); + } else if (direction === "column") { + node.setFlexDirectionColumn(); + } else if (direction === "rowReverse") { + node.setFlexDirectionRowReverse(); + } else if (direction === "columnReverse") { + node.setFlexDirectionColumnReverse(); + } else { + throw "setFlexDirection invalid param"; + } + } + + function setOtherNodeProps(child, node) { + node.minHeight = child.minHeight; + node.minWidth = child.minWidth; + node.flexShrink = child.flexShrink; + node.flexGrow = child.flexGrow; + + node.marginTop = child.marginTop; + node.marginLeft = child.marginLeft; + node.marginRight = child.marginRight; + node.marginBottom = child.marginBottom; + + node.paddingTop = child.paddingTop; + node.paddingLeft = child.paddingLeft; + node.paddingRight = child.paddingRight; + node.paddingBottom = child.paddingBottom; + + node.height = child.height; + node.width = child.width; + } + + function setDefaultNodeProps(child, node) { + node.minHeight = 9999; + node.minWidth = 0; + node.flexShrink = 0; + node.flexGrow = 0; + + node.marginTop = 0; + node.marginLeft = 0; + node.marginRight = 0; + node.marginBottom = 0; + + node.paddingTop = 0; + node.paddingLeft = 0; + node.paddingRight = 0; + node.paddingBottom = 0; + + node.height = child.height; + node.width = child.width; + + node.setDisplayFlex(); + + node.setAlignSelfAuto(); + node.setAlignItemsAuto(); + node.setAlignContentAuto(); + + node.setJustifySpaceBetween(); + node.setNoWrap(); + + node.setFlexDirectionRow(); + } + + function processNode(child, node) { + setOtherNodeProps(child, node, true); + setJustifyContent(child, node); + setFlexDirection(child, node); + setAlignContent(child, node); + setAlignItems(child, node); + setAlignSelf(child, node); + setFlexWrap(child, node); + setDisplay(child, node); + } + + function updatePositions() { + if (flex.height != 0 && flex.width != 0) { + var rootNode = flexLayoutService.createNode(); + processNode(flex, rootNode); + var nodes = [] + var node = {} + var child = {} + var i = 0; + for (i = 0; i !== flex.children.length; i++) { + node = flexLayoutService.createNode(); + child = flex.children[i]; + if (isFlex(child)) { + processNode(child, node); + } else { + setDefaultNodeProps(child, node); + } + nodes.push(node); + } + rootNode.appendChildren(nodes); + rootNode.calculateLayoutLtr(flex.width, flex.height); + /* console.log(JSON.stringify({root: rootNode})); */ + for (i = 0; i !== flex.children.length; i++) { + node = nodes[i]; + flex.children[i].x = node.getLayoutLeft(); + flex.children[i].y = node.getLayoutTop(); + flex.children[i].width = node.getLayoutWidth(); + flex.children[i].height = node.getLayoutHeight(); + /* console.log(JSON.stringify(node)); */ + } + flexLayoutService.collectGarbage(rootNode); + return true; + } else { + return false; + } + } + + onChildrenChanged: updatePositions(); + onWidthChanged: updatePositions(); + onHeightChanged: updatePositions(); +} diff --git a/doric-Qt/doric/resources/hlayout.qml b/doric-Qt/doric/resources/hlayout.qml index 1b918705..58f0df49 100644 --- a/doric-Qt/doric/resources/hlayout.qml +++ b/doric-Qt/doric/resources/hlayout.qml @@ -1,5 +1,22 @@ import QtQuick 2.12 import QtQuick.Controls 2.5 -Row { +Flex { + height: 400 + width: 675 + + flexDirection: "row" + flexWrap: "wrap" + justifyContent: "spaceAround" + alignItems: "center" + alignSelf: "center" + alignContent: "stretch" + + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } + Rectangle { color: "green"; height: 150; width: 150 } } diff --git a/doric-Qt/doric/widget/flex/FlexLayout.cpp b/doric-Qt/doric/widget/flex/FlexLayout.cpp new file mode 100644 index 00000000..df513205 --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayout.cpp @@ -0,0 +1,341 @@ +#include "FlexLayout.h" + +FlexLayout::FlexLayout(FlexLayoutConfig *config, QObject *parent) + : QObject(parent) { + node = YGNodeNewWithConfig(config->getConfig()); + this->config = config; +} + +FlexLayout::~FlexLayout() { YGNodeFree(node); } + +YGNodeRef FlexLayout::getNode() { return node; } + +void FlexLayout::appendChildren(QVariant children) { + QJSValue child = qvariant_cast(children); + std::vector tmp; + if (child.isUndefined()) { + qCritical() << "FlexLayout appendChildren child undefined"; + } else if (!child.isArray()) { + qCritical() << "FlexLayout appendChildren child is not array"; + } else { + const int length = child.property("length").toInt(); + for (int i = 0; i != length; i++) { + FlexLayout *node = nullptr; + if (!tryCast(child.property(i), node)) { + qCritical() << "FlexLayout appendChildren child is not qobject"; + return; + } else { + node->setParent(this); + tmp.push_back(node->getNode()); + } + } + YGNodeSetChildren(this->node, tmp); + } +} + +int FlexLayout::getFlexGrow() { + return static_cast(YGNodeStyleGetFlexGrow(node)); +} + +void FlexLayout::setFlexGrow(int v) { + YGNodeStyleSetFlexGrow(node, static_cast(v)); +} + +int FlexLayout::getFlexShrink() { + return static_cast(YGNodeStyleGetFlexShrink(node)); +} + +void FlexLayout::setFlexShrink(int v) { + YGNodeStyleSetFlexShrink(node, static_cast(v)); +} + +int FlexLayout::getHeight() { + return static_cast(YGNodeStyleGetHeight(node).value); +} + +void FlexLayout::setHeight(int points) { + YGNodeStyleSetHeight(node, static_cast(points)); +} + +int FlexLayout::getMinHeight() { + return static_cast(YGNodeStyleGetMinHeight(node).value); +} + +void FlexLayout::setMinHeight(int point) { + YGNodeStyleSetMinHeight(node, static_cast(point)); +} + +int FlexLayout::getWidth() { + return static_cast(YGNodeStyleGetWidth(node).value); +} + +void FlexLayout::setWidth(int points) { + YGNodeStyleSetWidth(node, static_cast(points)); +} + +int FlexLayout::getMinWidth() { + return static_cast(YGNodeStyleGetMinWidth(node).value); +} + +void FlexLayout::setMinWidth(int point) { + YGNodeStyleSetMinWidth(node, static_cast(point)); +} + +void FlexLayout::setDisplayNone() { + YGNodeStyleSetDisplay(node, YGDisplayNone); +} + +void FlexLayout::setDisplayFlex() { + YGNodeStyleSetDisplay(node, YGDisplayFlex); +} + +void FlexLayout::setFlexDirectionRow() { + YGNodeStyleSetFlexDirection(node, YGFlexDirectionRow); +} + +void FlexLayout::setFlexDirectionRowReverse() { + YGNodeStyleSetFlexDirection(node, YGFlexDirectionRowReverse); +} + +void FlexLayout::setFlexDirectionColumn() { + YGNodeStyleSetFlexDirection(node, YGFlexDirectionColumn); +} + +void FlexLayout::setFlexDirectionColumnReverse() { + YGNodeStyleSetFlexDirection(node, YGFlexDirectionColumnReverse); +} + +void FlexLayout::setJustifyCenter() { + YGNodeStyleSetJustifyContent(node, YGJustifyCenter); +} + +void FlexLayout::setJustifyFlexStart() { + YGNodeStyleSetJustifyContent(node, YGJustifyFlexStart); +} + +void FlexLayout::setJustifyFlexEnd() { + YGNodeStyleSetJustifyContent(node, YGJustifyFlexEnd); +} + +void FlexLayout::setJustifySpaceAround() { + YGNodeStyleSetJustifyContent(node, YGJustifySpaceAround); +} + +void FlexLayout::setJustifySpaceEvenly() { + YGNodeStyleSetJustifyContent(node, YGJustifySpaceEvenly); +} + +void FlexLayout::setJustifySpaceBetween() { + YGNodeStyleSetJustifyContent(node, YGJustifySpaceBetween); +} + +void FlexLayout::setAlignContentAuto() { + YGNodeStyleSetAlignContent(node, YGAlignAuto); +} + +void FlexLayout::setAlignContentCenter() { + YGNodeStyleSetAlignContent(node, YGAlignCenter); +} + +void FlexLayout::setAlignContentFlexEnd() { + YGNodeStyleSetAlignContent(node, YGAlignFlexEnd); +} + +void FlexLayout::setAlignContentStretch() { + YGNodeStyleSetAlignContent(node, YGAlignStretch); +} + +void FlexLayout::setAlignContentBaseline() { + YGNodeStyleSetAlignContent(node, YGAlignBaseline); +} + +void FlexLayout::setAlignContentFlexStart() { + YGNodeStyleSetAlignContent(node, YGAlignFlexStart); +} + +void FlexLayout::setAlignContentSpaceAround() { + YGNodeStyleSetAlignContent(node, YGAlignSpaceAround); +} + +void FlexLayout::setAlignContentSpaceBetween() { + YGNodeStyleSetAlignContent(node, YGAlignSpaceBetween); +} + +void FlexLayout::setAlignItemsAuto() { + YGNodeStyleSetAlignItems(node, YGAlignAuto); +} + +void FlexLayout::setAlignItemsCenter() { + YGNodeStyleSetAlignItems(node, YGAlignCenter); +} + +void FlexLayout::setAlignItemsFlexEnd() { + YGNodeStyleSetAlignItems(node, YGAlignFlexEnd); +} + +void FlexLayout::setAlignItemsStretch() { + YGNodeStyleSetAlignItems(node, YGAlignStretch); +} + +void FlexLayout::setAlignItemsBaseline() { + YGNodeStyleSetAlignItems(node, YGAlignBaseline); +} + +void FlexLayout::setAlignItemsFlexStart() { + YGNodeStyleSetAlignItems(node, YGAlignFlexStart); +} + +void FlexLayout::setAlignItemsSpaceAround() { + YGNodeStyleSetAlignItems(node, YGAlignSpaceAround); +} + +void FlexLayout::setAlignItemsSpaceBetween() { + YGNodeStyleSetAlignItems(node, YGAlignSpaceBetween); +} + +void FlexLayout::setAlignSelfAuto() { + YGNodeStyleSetAlignSelf(node, YGAlignAuto); +} + +void FlexLayout::setAlignSelfCenter() { + YGNodeStyleSetAlignSelf(node, YGAlignCenter); +} + +void FlexLayout::setAlignSelfFlexEnd() { + YGNodeStyleSetAlignSelf(node, YGAlignFlexEnd); +} + +void FlexLayout::setAlignSelfStretch() { + YGNodeStyleSetAlignSelf(node, YGAlignStretch); +} + +void FlexLayout::setAlignSelfBaseline() { + YGNodeStyleSetAlignSelf(node, YGAlignBaseline); +} + +void FlexLayout::setAlignSelfFlexStart() { + YGNodeStyleSetAlignSelf(node, YGAlignFlexStart); +} + +void FlexLayout::setAlignSelfSpaceAround() { + YGNodeStyleSetAlignSelf(node, YGAlignSpaceAround); +} + +void FlexLayout::setAlignSelfSpaceBetween() { + YGNodeStyleSetAlignSelf(node, YGAlignSpaceBetween); +} + +void FlexLayout::setWrap() { YGNodeStyleSetFlexWrap(node, YGWrapWrap); } + +void FlexLayout::setNoWrap() { YGNodeStyleSetFlexWrap(node, YGWrapNoWrap); } + +void FlexLayout::setWrapReverse() { + YGNodeStyleSetFlexWrap(node, YGWrapWrapReverse); +} + +int FlexLayout::getMarginTop() { + return static_cast(YGNodeStyleGetMargin(node, YGEdgeTop).value); +} + +void FlexLayout::setMarginTop(int point) { + YGNodeStyleSetMargin(node, YGEdgeTop, static_cast(point)); +} + +int FlexLayout::getMarginLeft() { + return static_cast(YGNodeStyleGetMargin(node, YGEdgeLeft).value); +} + +void FlexLayout::setMarginLeft(int point) { + YGNodeStyleSetMargin(node, YGEdgeLeft, static_cast(point)); +} + +int FlexLayout::getMarginRight() { + return static_cast(YGNodeStyleGetMargin(node, YGEdgeRight).value); +} + +void FlexLayout::setMarginRight(int point) { + YGNodeStyleSetMargin(node, YGEdgeRight, static_cast(point)); +} + +int FlexLayout::getMarginBottom() { + return static_cast(YGNodeStyleGetMargin(node, YGEdgeBottom).value); +} + +void FlexLayout::setMarginBottom(int point) { + YGNodeStyleSetMargin(node, YGEdgeBottom, static_cast(point)); +} + +int FlexLayout::getPaddingTop() { + return static_cast(YGNodeStyleGetPadding(node, YGEdgeTop).value); +} + +void FlexLayout::setPaddingTop(int point) { + YGNodeStyleSetPadding(node, YGEdgeTop, static_cast(point)); +} + +int FlexLayout::getPaddingLeft() { + return static_cast(YGNodeStyleGetPadding(node, YGEdgeLeft).value); +} + +void FlexLayout::setPaddingLeft(int point) { + YGNodeStyleSetPadding(node, YGEdgeLeft, static_cast(point)); +} + +int FlexLayout::getPaddingRight() { + return static_cast(YGNodeStyleGetPadding(node, YGEdgeRight).value); +} + +void FlexLayout::setPaddingRight(int point) { + YGNodeStyleSetPadding(node, YGEdgeRight, static_cast(point)); +} + +int FlexLayout::getPaddingBottom() { + return static_cast(YGNodeStyleGetPadding(node, YGEdgeBottom).value); +} + +void FlexLayout::setPaddingBottom(int point) { + YGNodeStyleSetPadding(node, YGEdgeBottom, static_cast(point)); +} + +int FlexLayout::getLayoutTop() { + return static_cast(YGNodeLayoutGetTop(node)); +} + +int FlexLayout::getLayoutLeft() { + return static_cast(YGNodeLayoutGetLeft(node)); +} + +int FlexLayout::getLayoutRight() { + return static_cast(YGNodeLayoutGetRight(node)); +} + +int FlexLayout::getLayoutBottom() { + return static_cast(YGNodeLayoutGetBottom(node)); +} + +int FlexLayout::getLayoutWidth() { + return static_cast(YGNodeLayoutGetWidth(node)); +} + +int FlexLayout::getLayoutHeight() { + return static_cast(YGNodeLayoutGetHeight(node)); +} + +void FlexLayout::calculateLayoutRtl(int width, int height) { + YGNodeCalculateLayout(node, static_cast(width), + static_cast(height), YGDirectionRTL); +} + +void FlexLayout::calculateLayoutLtr(int width, int height) { + YGNodeCalculateLayout(node, static_cast(width), + static_cast(height), YGDirectionLTR); +} + +bool FlexLayout::tryCast(QJSValue src, FlexLayout *&dst) { + if (!src.isQObject()) { + return false; + } else { + dst = qobject_cast(src.toQObject()); + return dst != nullptr; + } +} diff --git a/doric-Qt/doric/widget/flex/FlexLayout.h b/doric-Qt/doric/widget/flex/FlexLayout.h new file mode 100644 index 00000000..316fa0f7 --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayout.h @@ -0,0 +1,141 @@ +#ifndef FLEXLAYOUT_H +#define FLEXLAYOUT_H + +#include +#include +#include +#include + +#include "yoga/Yoga.h" +#include "FlexLayoutConfig.h" + +class FlexLayout : public QObject { + Q_OBJECT + + Q_PROPERTY(int flexShrink READ getFlexShrink WRITE setFlexShrink) + Q_PROPERTY(int flexGrow READ getFlexGrow WRITE setFlexGrow) + + Q_PROPERTY(int minHeight READ getHeight WRITE setHeight) + Q_PROPERTY(int height READ getHeight WRITE setHeight) + Q_PROPERTY(int minWidth READ getWidth WRITE setWidth) + Q_PROPERTY(int width READ getWidth WRITE setWidth) + + Q_PROPERTY(int marginTop READ getMarginTop WRITE setMarginTop) + Q_PROPERTY(int marginLeft READ getMarginLeft WRITE setMarginLeft) + Q_PROPERTY(int marginRight READ getMarginRight WRITE setMarginRight) + Q_PROPERTY(int marginBottom READ getMarginBottom WRITE setMarginBottom) + + Q_PROPERTY(int paddingTop READ getPaddingTop WRITE setPaddingTop) + Q_PROPERTY(int paddingLeft READ getPaddingLeft WRITE setPaddingLeft) + Q_PROPERTY(int paddingRight READ getPaddingRight WRITE setPaddingRight) + Q_PROPERTY(int paddingBottom READ getPaddingBottom WRITE setPaddingBottom) + + Q_PROPERTY(int layoutTop READ getLayoutTop) + Q_PROPERTY(int layoutLeft READ getLayoutLeft) + Q_PROPERTY(int layoutRight READ getLayoutRight) + Q_PROPERTY(int layoutBottom READ getLayoutBottom) + +private: + YGNodeRef node; + FlexLayoutConfig *config; + +public: + FlexLayout(FlexLayoutConfig *config, QObject *parent = nullptr); + virtual ~FlexLayout(); + YGNodeRef getNode(); +public slots: + /* child */ + Q_INVOKABLE void appendChildren(QVariant children); + /* flex */ + int getFlexGrow(); + void setFlexGrow(int v); + int getFlexShrink(); + void setFlexShrink(int v); + /* height */ + int getHeight(); + void setHeight(int point); + int getMinHeight(); + void setMinHeight(int point); + /* width */ + int getWidth(); + void setWidth(int point); + int getMinWidth(); + void setMinWidth(int point); + /* display */ + Q_INVOKABLE void setDisplayNone(); + Q_INVOKABLE void setDisplayFlex(); + /* flex-direction */ + Q_INVOKABLE void setFlexDirectionRow(); + Q_INVOKABLE void setFlexDirectionRowReverse(); + Q_INVOKABLE void setFlexDirectionColumn(); + Q_INVOKABLE void setFlexDirectionColumnReverse(); + /* justify-content */ + Q_INVOKABLE void setJustifyCenter(); + Q_INVOKABLE void setJustifyFlexStart(); + Q_INVOKABLE void setJustifyFlexEnd(); + Q_INVOKABLE void setJustifySpaceAround(); + Q_INVOKABLE void setJustifySpaceEvenly(); + Q_INVOKABLE void setJustifySpaceBetween(); + /* align-content */ + Q_INVOKABLE void setAlignContentAuto(); + Q_INVOKABLE void setAlignContentCenter(); + Q_INVOKABLE void setAlignContentFlexEnd(); + Q_INVOKABLE void setAlignContentStretch(); + Q_INVOKABLE void setAlignContentBaseline(); + Q_INVOKABLE void setAlignContentFlexStart(); + Q_INVOKABLE void setAlignContentSpaceAround(); + Q_INVOKABLE void setAlignContentSpaceBetween(); + /* align-items */ + Q_INVOKABLE void setAlignItemsAuto(); + Q_INVOKABLE void setAlignItemsCenter(); + Q_INVOKABLE void setAlignItemsFlexEnd(); + Q_INVOKABLE void setAlignItemsStretch(); + Q_INVOKABLE void setAlignItemsBaseline(); + Q_INVOKABLE void setAlignItemsFlexStart(); + Q_INVOKABLE void setAlignItemsSpaceAround(); + Q_INVOKABLE void setAlignItemsSpaceBetween(); + /* align-self */ + Q_INVOKABLE void setAlignSelfAuto(); + Q_INVOKABLE void setAlignSelfCenter(); + Q_INVOKABLE void setAlignSelfFlexEnd(); + Q_INVOKABLE void setAlignSelfStretch(); + Q_INVOKABLE void setAlignSelfBaseline(); + Q_INVOKABLE void setAlignSelfFlexStart(); + Q_INVOKABLE void setAlignSelfSpaceAround(); + Q_INVOKABLE void setAlignSelfSpaceBetween(); + /* flex-wrap */ + Q_INVOKABLE void setWrap(); + Q_INVOKABLE void setNoWrap(); + Q_INVOKABLE void setWrapReverse(); + /* margin */ + int getMarginTop(); + void setMarginTop(int point); + int getMarginLeft(); + void setMarginLeft(int point); + int getMarginRight(); + void setMarginRight(int point); + int getMarginBottom(); + void setMarginBottom(int point); + /* padding */ + int getPaddingTop(); + void setPaddingTop(int point); + int getPaddingLeft(); + void setPaddingLeft(int point); + int getPaddingRight(); + void setPaddingRight(int point); + int getPaddingBottom(); + void setPaddingBottom(int point); + /* calculate */ + int getLayoutTop(); + int getLayoutLeft(); + int getLayoutRight(); + int getLayoutBottom(); + int getLayoutWidth(); + int getLayoutHeight(); + Q_INVOKABLE void calculateLayoutRtl(int width, int height); + Q_INVOKABLE void calculateLayoutLtr(int width, int height); + +private: + static bool tryCast(QJSValue src, FlexLayout *&dst); +}; +#endif // FLEXLAYOUT_H diff --git a/doric-Qt/doric/widget/flex/FlexLayoutConfig.cpp b/doric-Qt/doric/widget/flex/FlexLayoutConfig.cpp new file mode 100644 index 00000000..b32f8a69 --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayoutConfig.cpp @@ -0,0 +1,9 @@ +#include "FlexLayoutConfig.h" + +FlexLayoutConfig::FlexLayoutConfig(QObject *parent) : QObject(parent) { + config = YGConfigNew(); +} + +FlexLayoutConfig::~FlexLayoutConfig() { YGConfigFree(config); } + +YGConfigRef FlexLayoutConfig::getConfig() const { return config; } diff --git a/doric-Qt/doric/widget/flex/FlexLayoutConfig.h b/doric-Qt/doric/widget/flex/FlexLayoutConfig.h new file mode 100644 index 00000000..b56ae395 --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayoutConfig.h @@ -0,0 +1,20 @@ +#ifndef FLEXLAYOUTCONFIG_H +#define FLEXLAYOUTCONFIG_H + +#include +#include + +#include "yoga/Yoga.h" + +class FlexLayoutConfig : public QObject { + Q_OBJECT +private: + YGConfigRef config; + +public: + explicit FlexLayoutConfig(QObject *parent = nullptr); + virtual ~FlexLayoutConfig(); + YGConfigRef getConfig() const; +}; + +#endif // FLEXLAYOUTCONFIG_H diff --git a/doric-Qt/doric/widget/flex/FlexLayoutService.cpp b/doric-Qt/doric/widget/flex/FlexLayoutService.cpp new file mode 100644 index 00000000..e37fb07f --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayoutService.cpp @@ -0,0 +1,35 @@ +#include "FlexLayoutService.h" + +FlexLayoutService::FlexLayoutService(QObject *parent) : QObject(parent) { + config = new FlexLayoutConfig(this); +} + +FlexLayoutService::~FlexLayoutService() {} + +QVariant FlexLayoutService::createNode(QVariant config) { + FlexLayoutConfig *object = qvariant_cast(config); + QVariant result; + if (object == nullptr) { + qCritical() << "FlexLayoutService createNode config not FlexLayoutConfig*"; + } else { + result = QVariant::fromValue(new FlexLayout(object, this)); + } + return result; +} + +void FlexLayoutService::collectGarbage(QVariant rootNode) { + FlexLayout *node = qvariant_cast(rootNode); + if (node == nullptr) { + qCritical() << "FlexLayoutService collectGarbage node to FlexLayout*"; + } else { + node->deleteLater(); + } +} + +QVariant FlexLayoutService::createConfig() { + return QVariant::fromValue(new FlexLayoutConfig(this)); +} + +QVariant FlexLayoutService::createNode() { + return QVariant::fromValue(new FlexLayout(config, this)); +} diff --git a/doric-Qt/doric/widget/flex/FlexLayoutService.h b/doric-Qt/doric/widget/flex/FlexLayoutService.h new file mode 100644 index 00000000..860e3f09 --- /dev/null +++ b/doric-Qt/doric/widget/flex/FlexLayoutService.h @@ -0,0 +1,29 @@ +#ifndef FLEXLAYOUTSERVICE_H +#define FLEXLAYOUTSERVICE_H + +#include +#include +#include +#include + +#include "FlexLayoutConfig.h" +#include "FlexLayout.h" + +#include "yoga/Yoga.h" + +class FlexLayoutService : public QObject { + Q_OBJECT +private: + FlexLayoutConfig *config; + +public: + explicit FlexLayoutService(QObject *parent = nullptr); + virtual ~FlexLayoutService(); +public slots: + QVariant createConfig(); + QVariant createNode(); + QVariant createNode(QVariant config); + void collectGarbage(QVariant rootNode); +}; + +#endif // FLEXLAYOUTSERVICE_H