You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1213 lines
38 KiB
1213 lines
38 KiB
4 years ago
|
/**
|
||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||
|
* or more contributor license agreements. See the NOTICE file
|
||
|
* distributed with this work for additional information
|
||
|
* regarding copyright ownership. The ASF licenses this file
|
||
|
* to you under the Apache License, Version 2.0 (the
|
||
|
* "License"); you may not use this file except in compliance
|
||
|
* with the License. You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing,
|
||
|
* software distributed under the License is distributed on an
|
||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||
|
* KIND, either express or implied. See the License for the
|
||
|
* specific language governing permissions and limitations
|
||
|
* under the License.
|
||
|
*/
|
||
|
#ifdef __cplusplus
|
||
|
|
||
|
#ifndef WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
|
||
|
#define WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
|
||
|
|
||
|
#include <string.h>
|
||
|
#include <math.h>
|
||
|
#include <vector>
|
||
|
#include <iostream>
|
||
|
#include <string>
|
||
|
#include <algorithm>
|
||
|
#include "style.h"
|
||
|
#include "flex_enum.h"
|
||
|
|
||
|
namespace WeexCore {
|
||
|
|
||
|
class WXCoreLayoutNode;
|
||
|
|
||
|
class WXCoreFlexLine;
|
||
|
|
||
|
enum FormattingContext {
|
||
|
kBFC,
|
||
|
kNonBFC,
|
||
|
} ;
|
||
|
|
||
|
enum MeasureMode {
|
||
|
kUnspecified = 0,
|
||
|
kExactly,
|
||
|
} ;
|
||
|
|
||
|
struct WXCoreSize {
|
||
|
private:
|
||
|
float hypotheticalWidth;
|
||
|
float hypotheticalHeight;
|
||
|
public:
|
||
|
friend class WXCoreLayoutNode;
|
||
|
float width;
|
||
|
float height;
|
||
|
|
||
|
WXCoreSize() : hypotheticalWidth(NAN),
|
||
|
hypotheticalHeight(NAN),
|
||
|
width(0), height(0) {}
|
||
|
|
||
|
inline void reset() {
|
||
|
hypotheticalWidth = NAN ;
|
||
|
hypotheticalHeight = NAN;
|
||
|
width = 0;
|
||
|
height = 0;
|
||
|
}
|
||
|
|
||
|
inline bool isNAN() {
|
||
|
return isnan(width) || isnan(height);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* layout-result:layout-height、layout-width、position(left、right、top、bottom)、direction
|
||
|
*/
|
||
|
struct WXCorelayoutResult {
|
||
|
WXCoreDirection mLayoutDirection;
|
||
|
WXCoreSize mLayoutSize;
|
||
|
WXCorePosition mLayoutPosition;
|
||
|
|
||
|
inline bool isNAN() {
|
||
|
return mLayoutSize.isNAN() || mLayoutPosition.isNAN();
|
||
|
}
|
||
|
|
||
|
inline void reset() {
|
||
|
mLayoutSize.reset();
|
||
|
mLayoutPosition.reset();
|
||
|
mLayoutDirection = kDirectionInherit;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
typedef WXCoreSize(*WXCoreMeasureFunc)(WXCoreLayoutNode *node, float width,
|
||
|
MeasureMode widthMeasureMode,
|
||
|
float height, MeasureMode heightMeasureMode);
|
||
|
|
||
|
using Index = std::vector<WXCoreLayoutNode *>::size_type;
|
||
|
|
||
|
/**
|
||
|
* flie line
|
||
|
*/
|
||
|
class WXCoreFlexLine {
|
||
|
public:
|
||
|
float mMainSize;
|
||
|
|
||
|
float mCrossSize;
|
||
|
|
||
|
Index mItemCount;
|
||
|
|
||
|
float mTotalFlexGrow;
|
||
|
|
||
|
float mTotalFlexibleSize;
|
||
|
|
||
|
/**
|
||
|
* Store the indices of the children views whose mAlignSelf property is stretch.
|
||
|
* The stored indices are the absolute indices including all children in the Flexbox,
|
||
|
* not the relative indices in this flex line.
|
||
|
*/
|
||
|
std::vector<Index> mIndicesAlignSelfStretch;
|
||
|
|
||
|
WXCoreFlexLine() : mMainSize(0),
|
||
|
mCrossSize(0),
|
||
|
mItemCount(0),
|
||
|
mTotalFlexGrow(0),
|
||
|
mTotalFlexibleSize(0) {
|
||
|
}
|
||
|
|
||
|
~WXCoreFlexLine() {
|
||
|
mMainSize = 0;
|
||
|
mCrossSize = 0;
|
||
|
mItemCount = 0;
|
||
|
mTotalFlexGrow = 0;
|
||
|
mTotalFlexibleSize = 0;
|
||
|
mIndicesAlignSelfStretch.clear();
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Layout node
|
||
|
*/
|
||
|
class WXCoreLayoutNode {
|
||
|
|
||
|
public:
|
||
|
WXCoreLayoutNode() :
|
||
|
mParent(nullptr),
|
||
|
dirty(true),
|
||
|
widthDirty{false},
|
||
|
heightDirty{false},
|
||
|
mHasNewLayout(true),
|
||
|
mIsDestroy(false),
|
||
|
measureFunc(nullptr) {
|
||
|
mCssStyle = new WXCoreCSSStyle();
|
||
|
mLayoutResult = new WXCorelayoutResult();
|
||
|
}
|
||
|
|
||
|
virtual ~WXCoreLayoutNode() {
|
||
|
mIsDestroy = true;
|
||
|
mHasNewLayout = true;
|
||
|
dirty = true;
|
||
|
measureFunc = nullptr;
|
||
|
mParent = nullptr;
|
||
|
mChildList.clear();
|
||
|
BFCs.clear();
|
||
|
NonBFCs.clear();
|
||
|
mChildrenFrozen.clear();
|
||
|
|
||
|
for (WXCoreFlexLine *flexLine : mFlexLines) {
|
||
|
if (flexLine != nullptr) {
|
||
|
delete flexLine;
|
||
|
flexLine = nullptr;
|
||
|
}
|
||
|
}
|
||
|
mFlexLines.clear();
|
||
|
|
||
|
if (mCssStyle != nullptr) {
|
||
|
delete mCssStyle;
|
||
|
mCssStyle = nullptr;
|
||
|
}
|
||
|
|
||
|
if (mLayoutResult != nullptr) {
|
||
|
delete mLayoutResult;
|
||
|
mLayoutResult = nullptr;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
/**
|
||
|
* Holds the 'frozen' state of children during measure. If a view is frozen it will no longer
|
||
|
* expand regardless of mFlexGrow. Items are indexed by the child's
|
||
|
* reordered index.
|
||
|
*/
|
||
|
std::vector<bool> mChildrenFrozen;
|
||
|
|
||
|
std::vector<WXCoreFlexLine *> mFlexLines;
|
||
|
|
||
|
std::vector<WXCoreLayoutNode *> mChildList;
|
||
|
|
||
|
std::vector<WXCoreLayoutNode *> BFCs;
|
||
|
|
||
|
std::vector<WXCoreLayoutNode *> NonBFCs;
|
||
|
|
||
|
WXCoreLayoutNode *mParent = nullptr;
|
||
|
|
||
|
WXCoreCSSStyle *mCssStyle = nullptr;
|
||
|
|
||
|
MeasureMode widthMeasureMode = kUnspecified;
|
||
|
|
||
|
MeasureMode heightMeasureMode = kUnspecified;
|
||
|
|
||
|
WXCorelayoutResult *mLayoutResult = nullptr;
|
||
|
|
||
|
WXCorePosition *absoultePositon = nullptr;
|
||
|
|
||
|
bool mHasNewLayout;
|
||
|
|
||
|
bool dirty, widthDirty, heightDirty;
|
||
|
|
||
|
bool mIsDestroy = true;
|
||
|
|
||
|
bool mNeedsPlatformDependentLayout = false;
|
||
|
|
||
|
WXCoreMeasureFunc measureFunc = nullptr;
|
||
|
|
||
|
void *context = nullptr;
|
||
|
|
||
|
/** ================================ Cache:Last calculate result =================================== **/
|
||
|
|
||
|
public:
|
||
|
|
||
|
|
||
|
/** ================================ Engine Entry Function =================================== **/
|
||
|
|
||
|
void calculateLayout(const std::pair<float,float>&);
|
||
|
|
||
|
/** ================================ measureFunc =================================== **/
|
||
|
|
||
|
inline void setMeasureFunc(WXCoreMeasureFunc measure) {
|
||
|
measureFunc = measure;
|
||
|
markDirty();
|
||
|
}
|
||
|
|
||
|
inline bool haveMeasureFunc() const {
|
||
|
return nullptr != measureFunc;
|
||
|
}
|
||
|
|
||
|
inline WXCoreMeasureFunc getMeasureFunc() const {
|
||
|
return measureFunc;
|
||
|
}
|
||
|
|
||
|
/** ================================ context =================================== **/
|
||
|
|
||
|
|
||
|
inline void *getContext() const {
|
||
|
return context;
|
||
|
}
|
||
|
|
||
|
inline void setContext(void * const context) {
|
||
|
this->context = context;
|
||
|
}
|
||
|
|
||
|
inline void copyStyle(WXCoreLayoutNode *srcNode) {
|
||
|
if (srcNode != nullptr && memcmp(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle)) != 0) {
|
||
|
memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void copyFrom(WXCoreLayoutNode* srcNode){
|
||
|
if (srcNode == nullptr) return;
|
||
|
|
||
|
memcpy(mCssStyle, srcNode->mCssStyle, sizeof(WXCoreCSSStyle));
|
||
|
}
|
||
|
|
||
|
inline void copyMeasureFunc(WXCoreLayoutNode *srcNode) {
|
||
|
if (srcNode != nullptr && memcmp(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc)) != 0) {
|
||
|
memcpy(&measureFunc, &srcNode->measureFunc, sizeof(WXCoreMeasureFunc));
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** ================================ custom =================================== **/
|
||
|
inline bool getNeedsPlatformDependentLayout() const {
|
||
|
return mNeedsPlatformDependentLayout;
|
||
|
}
|
||
|
|
||
|
inline void setNeedsPlatformDependentLayout(bool v) {
|
||
|
this->mNeedsPlatformDependentLayout = v;
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
|
||
|
/** ================================ measure =================================== **/
|
||
|
|
||
|
inline void reset() {
|
||
|
if (isDirty()) {
|
||
|
mLayoutResult->reset();
|
||
|
for (WXCoreFlexLine *flexLine : mFlexLines) {
|
||
|
if (flexLine != nullptr) {
|
||
|
delete flexLine;
|
||
|
flexLine = nullptr;
|
||
|
}
|
||
|
}
|
||
|
mFlexLines.clear();
|
||
|
|
||
|
mChildrenFrozen.assign(getChildCount(kNonBFC), false);
|
||
|
}
|
||
|
widthMeasureMode = isnan(mCssStyle->mStyleWidth) ? kUnspecified : kExactly;
|
||
|
heightMeasureMode = isnan(mCssStyle->mStyleHeight) ? kUnspecified : kExactly;
|
||
|
}
|
||
|
|
||
|
inline void setLayoutWidth(const float width) {
|
||
|
if (mLayoutResult->mLayoutSize.width != width &&
|
||
|
(!isnan(width) || !isnan(mLayoutResult->mLayoutSize.width))) {
|
||
|
mLayoutResult->mLayoutSize.width = width;
|
||
|
widthDirty = true;
|
||
|
markDirty(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setLayoutHeight(const float height) {
|
||
|
if (mLayoutResult->mLayoutSize.height != height &&
|
||
|
(!isnan(height) || !isnan(mLayoutResult->mLayoutSize.height))) {
|
||
|
mLayoutResult->mLayoutSize.height = height;
|
||
|
heightDirty = true;
|
||
|
markDirty(false);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setWidthMeasureMode(const MeasureMode measureMode) {
|
||
|
if (widthMeasureMode != measureMode) {
|
||
|
widthMeasureMode = measureMode;
|
||
|
if (getChildCount(kNonBFC) > 0) {
|
||
|
widthDirty = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setHeightMeasureMode(const MeasureMode measureMode) {
|
||
|
if (heightMeasureMode != measureMode) {
|
||
|
heightMeasureMode = measureMode;
|
||
|
if (getChildCount(kNonBFC) > 0) {
|
||
|
heightDirty = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float firstLineCrossSize() const {
|
||
|
float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
|
||
|
if (!mFlexLines.empty()) {
|
||
|
sum += mFlexLines[0]->mCrossSize;
|
||
|
}
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
inline float getSumOfCrossSize() const {
|
||
|
float sum = sumPaddingBorderAlongAxis(this, !isMainAxisHorizontal(this));
|
||
|
for (WXCoreFlexLine *flexLine: mFlexLines) {
|
||
|
sum += flexLine->mCrossSize;
|
||
|
}
|
||
|
return sum;
|
||
|
}
|
||
|
|
||
|
inline bool isMainAxisHorizontal(const WXCoreLayoutNode* const node) const {
|
||
|
return node->mCssStyle->mFlexDirection == kFlexDirectionRow ||
|
||
|
node->mCssStyle->mFlexDirection == kFlexDirectionRowReverse;
|
||
|
}
|
||
|
|
||
|
inline bool isCrossExactly() const {
|
||
|
return isMainAxisHorizontal(this) ? heightMeasureMode == kExactly
|
||
|
: widthMeasureMode == kExactly;
|
||
|
}
|
||
|
|
||
|
inline float sumPaddingBorderAlongAxis(const WXCoreLayoutNode* const node, bool horizontal) const {
|
||
|
float paddingBorderAlongAxis;
|
||
|
if (horizontal) {
|
||
|
paddingBorderAlongAxis =
|
||
|
node->mCssStyle->mPadding.getPadding(kPaddingLeft) +
|
||
|
node->mCssStyle->mPadding.getPadding(kPaddingRight) +
|
||
|
node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft) +
|
||
|
node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
|
||
|
} else {
|
||
|
paddingBorderAlongAxis =
|
||
|
node->mCssStyle->mPadding.getPadding(kPaddingTop) +
|
||
|
node->mCssStyle->mPadding.getPadding(kPaddingBottom) +
|
||
|
node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop) +
|
||
|
node->mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
|
||
|
}
|
||
|
return paddingBorderAlongAxis;
|
||
|
}
|
||
|
|
||
|
inline bool isWrapRequired(const float &width, const float &height,
|
||
|
const float ¤tLength, const float &childLength) const {
|
||
|
float freeMainSize = CalculateFreeSpaceAlongMainAxis(width, height, currentLength);
|
||
|
return !isSingleFlexLine(freeMainSize) && freeMainSize < childLength;
|
||
|
}
|
||
|
|
||
|
//If width/height is NAN, ret is NAN, which property we use on purpose.
|
||
|
virtual float CalculateFreeSpaceAlongMainAxis(const float &width, const float &height,
|
||
|
const float ¤tLength) const{
|
||
|
float ret;
|
||
|
if(isMainAxisHorizontal(this)){
|
||
|
ret = width - sumPaddingBorderAlongAxis(this, true) - currentLength;
|
||
|
}
|
||
|
else{
|
||
|
ret = height - sumPaddingBorderAlongAxis(this, false) - currentLength;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
inline bool isSingleFlexLine(const float &mainSize) const {
|
||
|
return mCssStyle->mFlexWrap == kNoWrap || isnan(mainSize);
|
||
|
}
|
||
|
|
||
|
inline void sumFlexGrow(const WXCoreLayoutNode* const child, WXCoreFlexLine* const flexLine, Index i){
|
||
|
if (child->mCssStyle->mFlexGrow > 0) {
|
||
|
flexLine->mTotalFlexGrow += child->mCssStyle->mFlexGrow;
|
||
|
mChildrenFrozen[i] = false;
|
||
|
if (isMainAxisHorizontal(this)) {
|
||
|
if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalWidth)) {
|
||
|
flexLine->mTotalFlexibleSize += child->mLayoutResult->mLayoutSize.hypotheticalWidth;
|
||
|
}
|
||
|
} else {
|
||
|
if (!isnan(child->mLayoutResult->mLayoutSize.hypotheticalHeight)) {
|
||
|
flexLine->mTotalFlexibleSize += child->mLayoutResult->mLayoutSize.hypotheticalHeight;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
mChildrenFrozen[i] = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setMeasuredDimensionForFlex(
|
||
|
const float width, const MeasureMode widthMeasureMode,
|
||
|
const float height, const MeasureMode heightMeasureMode){
|
||
|
float actualWidth, actualHeight;
|
||
|
if (isMainAxisHorizontal(this)) {
|
||
|
actualWidth = widthMeasureMode == kExactly ? width : getLargestMainSize();
|
||
|
actualHeight = heightMeasureMode == kExactly ? height : getSumOfCrossSize();
|
||
|
} else {
|
||
|
actualHeight = heightMeasureMode == kExactly ? height : getLargestMainSize();
|
||
|
actualWidth = widthMeasureMode == kExactly ? width : firstLineCrossSize();
|
||
|
}
|
||
|
setMeasuredDimension(actualWidth, actualHeight);
|
||
|
}
|
||
|
|
||
|
inline float calcItemSizeAlongAxis(const WXCoreLayoutNode* const node, const bool horizontal, const bool useHypotheticalSize = false) const {
|
||
|
float ret;
|
||
|
if (horizontal) {
|
||
|
ret = node->mCssStyle->mMargin.getMargin(kMarginLeft) +
|
||
|
node->mCssStyle->mMargin.getMargin(kMarginRight);
|
||
|
ret += useHypotheticalSize ? node->mLayoutResult->mLayoutSize.hypotheticalWidth
|
||
|
: node->mLayoutResult->mLayoutSize.width;
|
||
|
} else {
|
||
|
ret = node->mCssStyle->mMargin.getMargin(kMarginTop) +
|
||
|
node->mCssStyle->mMargin.getMargin(kMarginBottom);
|
||
|
ret += useHypotheticalSize ? node->mLayoutResult->mLayoutSize.hypotheticalHeight
|
||
|
: node->mLayoutResult->mLayoutSize.height;
|
||
|
}
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
inline void limitMainSizeForFlexGrow(WXCoreFlexLine* const flexLine, const Index childIndex,
|
||
|
const float flexGrow) {
|
||
|
mChildrenFrozen[childIndex] = true;
|
||
|
flexLine->mTotalFlexGrow -= flexGrow;
|
||
|
}
|
||
|
|
||
|
inline void setMeasuredDimension(const float width, const float height) {
|
||
|
mLayoutResult->mLayoutSize.width = width;
|
||
|
mLayoutResult->mLayoutSize.height = height;
|
||
|
}
|
||
|
|
||
|
inline std::pair<bool, float> limitChildMainSize(WXCoreFlexLine* const flexLine, const WXCoreLayoutNode* const child,
|
||
|
float childSizeAlongMainAxis, const Index childIndex){
|
||
|
bool needsReexpand = false;
|
||
|
if (isMainAxisHorizontal(this)) {
|
||
|
if (!isnan(child->mCssStyle->mMaxWidth) &&
|
||
|
childSizeAlongMainAxis > child->mCssStyle->mMaxWidth) {
|
||
|
needsReexpand = true;
|
||
|
childSizeAlongMainAxis = child->mCssStyle->mMaxWidth;
|
||
|
} else if (!isnan(child->mCssStyle->mMinWidth) &&
|
||
|
childSizeAlongMainAxis < child->mCssStyle->mMinWidth) {
|
||
|
needsReexpand = true;
|
||
|
childSizeAlongMainAxis = child->mCssStyle->mMinWidth;
|
||
|
}
|
||
|
} else {
|
||
|
if (!isnan(child->mCssStyle->mMaxHeight) &&
|
||
|
childSizeAlongMainAxis > child->mCssStyle->mMaxHeight) {
|
||
|
needsReexpand = true;
|
||
|
childSizeAlongMainAxis = child->mCssStyle->mMaxHeight;
|
||
|
} else if (!isnan(child->mCssStyle->mMinHeight) &&
|
||
|
childSizeAlongMainAxis < child->mCssStyle->mMinHeight) {
|
||
|
needsReexpand = true;
|
||
|
childSizeAlongMainAxis = child->mCssStyle->mMinHeight;
|
||
|
}
|
||
|
}
|
||
|
limitMainSizeForFlexGrow(flexLine, childIndex, child->mCssStyle->mFlexGrow);
|
||
|
return std::make_pair(needsReexpand, childSizeAlongMainAxis);
|
||
|
}
|
||
|
|
||
|
void updateLeftRightForAbsolute(float &left, float &right,
|
||
|
const WXCorePadding &parentPadding,
|
||
|
const WXCoreBorderWidth &parentBorder,
|
||
|
const WXCoreSize &parentSize) const {
|
||
|
if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft))) {
|
||
|
if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeRight))) {
|
||
|
;
|
||
|
} else {
|
||
|
right += parentSize.width -
|
||
|
(parentBorder.getBorderWidth(kBorderWidthRight) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
|
||
|
+ mLayoutResult->mLayoutSize.width);
|
||
|
left += parentSize.width -
|
||
|
(parentBorder.getBorderWidth(kBorderWidthRight) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeRight)
|
||
|
+ mLayoutResult->mLayoutSize.width);
|
||
|
}
|
||
|
} else {
|
||
|
left += parentBorder.getBorderWidth(kBorderWidthLeft) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
|
||
|
right += parentBorder.getBorderWidth(kBorderWidthLeft) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void updateTopBottomForAbsolute(float &top, float &bottom,
|
||
|
const WXCorePadding &parentPadding,
|
||
|
const WXCoreBorderWidth &parentBorder,
|
||
|
const WXCoreSize &parentSize) const {
|
||
|
if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeTop))) {
|
||
|
if (isnan(mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom))) {
|
||
|
;
|
||
|
} else {
|
||
|
top += parentSize.height -
|
||
|
(parentBorder.getBorderWidth(kBorderWidthBottom) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
|
||
|
+ mLayoutResult->mLayoutSize.height);
|
||
|
bottom += parentSize.height -
|
||
|
(parentBorder.getBorderWidth(kBorderWidthBottom) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom)
|
||
|
+ mLayoutResult->mLayoutSize.height);
|
||
|
}
|
||
|
} else {
|
||
|
top += parentBorder.getBorderWidth(kBorderWidthTop) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
|
||
|
bottom += parentBorder.getBorderWidth(kBorderWidthTop) +
|
||
|
mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** ================================ other =================================== **/
|
||
|
|
||
|
inline void clearDirty() {
|
||
|
dirty = false;
|
||
|
widthDirty = false;
|
||
|
heightDirty = false;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
measure(float, float, bool);
|
||
|
|
||
|
void hypotheticalMeasure(float, float, bool = false);
|
||
|
|
||
|
void measureLeafNode(float, float, bool, bool);
|
||
|
|
||
|
void measureInternalNode(float, float, bool, bool);
|
||
|
|
||
|
void updateCurrentFlexline(Index, WXCoreFlexLine *, Index, const WXCoreLayoutNode *, bool);
|
||
|
|
||
|
void measureChild(WXCoreLayoutNode* , float, float, float, bool, bool);
|
||
|
|
||
|
void adjustChildSize(WXCoreLayoutNode *, float);
|
||
|
|
||
|
void adjustChildSize(const WXCoreLayoutNode *child,
|
||
|
const float currentMainSize,
|
||
|
const float parentWidth,
|
||
|
const float parentHeight,
|
||
|
float &childWidth,
|
||
|
float &childHeight) const;
|
||
|
|
||
|
void stretchViewCrossSize();
|
||
|
|
||
|
void stretchViewCrossSize(WXCoreLayoutNode *, float);
|
||
|
|
||
|
Index expandItemsInFlexLine(WXCoreFlexLine *, float, Index);
|
||
|
|
||
|
void checkSizeConstraints(WXCoreLayoutNode *, bool);
|
||
|
|
||
|
void
|
||
|
determineMainSize(float width, float height);
|
||
|
|
||
|
void
|
||
|
determineCrossSize(float, float, bool);
|
||
|
|
||
|
void
|
||
|
determineCrossSize(float, float, WXCoreFlexLine *);
|
||
|
|
||
|
void setFrame(float, float, float, float);
|
||
|
|
||
|
void setFrame(WXCorePosition*,float, float, float, float);
|
||
|
|
||
|
/** ================================ layout =================================== **/
|
||
|
|
||
|
void layout(float left, float top, float right, float bottom, bool, const std::pair<float,float>* = nullptr);
|
||
|
|
||
|
void calcRelativeOffset(float &left, float &top, float &right, float &bottom) const ;
|
||
|
|
||
|
void calcAbsoluteOffset(float &left, float &top, float &right, float &bottom, const std::pair<float,float>* = nullptr);
|
||
|
|
||
|
void positionAbsoluteFlexItem(float &left, float &top, float &right, float &bottom);
|
||
|
|
||
|
void layoutHorizontal(bool isRtl, float left, float top, float right, float bottom,
|
||
|
WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
|
||
|
|
||
|
void layoutFlexlineHorizontal(const float width,
|
||
|
const WXCoreFlexLine *const flexLine,
|
||
|
float &childLeft,
|
||
|
float &childRight,
|
||
|
float &spaceBetweenItem) const;
|
||
|
|
||
|
void layoutSingleChildHorizontal(WXCoreLayoutNode *node, WXCoreFlexLine *flexLine,
|
||
|
WXCoreFlexWrap flexWrap, WXCoreAlignItems alignItems,
|
||
|
float, float, float, float, bool);
|
||
|
|
||
|
void layoutSingleChildHorizontal(const bool isRtl,
|
||
|
const bool,
|
||
|
float childBottom, float childTop,
|
||
|
WXCoreFlexLine *const flexLine,
|
||
|
WXCoreLayoutNode *const child,
|
||
|
float&, float&);
|
||
|
|
||
|
void layoutVertical(bool isRtl, bool fromBottomToTop, float left, float top, float right, float bottom,
|
||
|
WXCoreLayoutNode*, WXCoreFlexLine *const flexLine);
|
||
|
|
||
|
void layoutFlexlineVertical(const float height,
|
||
|
const WXCoreFlexLine *const flexLine,
|
||
|
float &childTop,
|
||
|
float &childBottom,
|
||
|
float &spaceBetweenItem) const;
|
||
|
void layoutSingleChildVertical(WXCoreLayoutNode *node, WXCoreFlexLine *flexLine,
|
||
|
bool isRtl, WXCoreAlignItems alignItems,
|
||
|
float, float, float, float, bool);
|
||
|
|
||
|
void layoutSingleChildVertical(const bool isRtl, const bool fromBottomToTop,
|
||
|
const bool absoluteFlexItem,
|
||
|
const float childLeft, const float childRight,
|
||
|
WXCoreFlexLine *const flexLine,
|
||
|
WXCoreLayoutNode *const child,
|
||
|
float& ,float&);
|
||
|
|
||
|
void updateFlexLineForAbsoluteItem(WXCoreLayoutNode *const absoluteFlexItem, WXCoreFlexLine *const flexLine);
|
||
|
|
||
|
void initFormatingContext(std::vector<WXCoreLayoutNode *> &BFCs);
|
||
|
|
||
|
std::pair<bool,float> calculateBFCWidth(float, float);
|
||
|
|
||
|
std::pair<bool,float> calculateBFCHeight(float, float);
|
||
|
|
||
|
std::tuple<bool, float, float> calculateBFCDimension(const std::pair<float,float>&);
|
||
|
|
||
|
virtual void OnLayoutBefore() {
|
||
|
|
||
|
}
|
||
|
|
||
|
virtual void OnLayoutAfter(float width, float height) {
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
public:
|
||
|
virtual void onLayout(float left, float top, float right, float bottom, WXCoreLayoutNode* = nullptr, WXCoreFlexLine *const flexLine = nullptr);
|
||
|
/** ================================ tree =================================== **/
|
||
|
|
||
|
inline Index getChildCount(FormattingContext formattingContext) const {
|
||
|
switch (formattingContext) {
|
||
|
case kNonBFC:
|
||
|
return NonBFCs.size();
|
||
|
case kBFC:
|
||
|
return BFCs.size();
|
||
|
default:
|
||
|
return mChildList.size();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline Index getChildCount() const {
|
||
|
return mChildList.size();
|
||
|
}
|
||
|
|
||
|
inline std::vector<WXCoreLayoutNode *>::const_iterator ChildListIterBegin() {
|
||
|
return mChildList.cbegin();
|
||
|
}
|
||
|
|
||
|
inline std::vector<WXCoreLayoutNode *>::const_iterator ChildListIterEnd() {
|
||
|
return mChildList.cend();
|
||
|
}
|
||
|
|
||
|
inline bool hasChild(const WXCoreLayoutNode* const child){
|
||
|
if(std::find(mChildList.begin(), mChildList.end(), child) != mChildList.end()){
|
||
|
return true;
|
||
|
}else{
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void removeChild(const WXCoreLayoutNode* const child) {
|
||
|
for (int index = 0; index < mChildList.size(); index++) {
|
||
|
if (child == mChildList[index]) {
|
||
|
mChildList.erase(mChildList.begin() + index);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
markDirty();
|
||
|
}
|
||
|
|
||
|
inline void addChildAt(WXCoreLayoutNode* const child, Index index) {
|
||
|
mChildList.insert(mChildList.begin() + index, child);
|
||
|
child->mParent = this;
|
||
|
markDirty();
|
||
|
}
|
||
|
|
||
|
inline WXCoreLayoutNode *getChildAt(const FormattingContext formattingContext, const Index index) const {
|
||
|
switch (formattingContext) {
|
||
|
case kNonBFC:
|
||
|
return NonBFCs[index];
|
||
|
case kBFC:
|
||
|
return BFCs[index];
|
||
|
default:
|
||
|
return mChildList[index];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreLayoutNode *getChildAt(const Index index) const {
|
||
|
return mChildList[index];
|
||
|
}
|
||
|
|
||
|
inline WXCoreLayoutNode *getParent() const {
|
||
|
return mParent;
|
||
|
}
|
||
|
|
||
|
inline void setParent(WXCoreLayoutNode * const parent, WXCoreLayoutNode * const child) const {
|
||
|
child->mParent = parent;
|
||
|
}
|
||
|
|
||
|
inline bool isBFC(WXCoreLayoutNode* const node) const {
|
||
|
return node->mCssStyle->mPositionType == kAbsolute || node->mCssStyle->mPositionType == kFixed;
|
||
|
}
|
||
|
|
||
|
/** ================================ margin =================================== **/
|
||
|
|
||
|
inline float getMarginTop() const {
|
||
|
return mCssStyle->mMargin.getMargin(kMarginTop);
|
||
|
}
|
||
|
|
||
|
inline float getMarginBottom() const {
|
||
|
return mCssStyle->mMargin.getMargin(kMarginBottom);
|
||
|
}
|
||
|
|
||
|
inline float getMarginLeft() const {
|
||
|
return mCssStyle->mMargin.getMargin(kMarginLeft);
|
||
|
}
|
||
|
|
||
|
inline float getMarginRight() const {
|
||
|
return mCssStyle->mMargin.getMargin(kMarginRight);
|
||
|
}
|
||
|
|
||
|
inline void setMargin(const WXCoreMarginEdge &edge, const float margin) {
|
||
|
if (mCssStyle->mMargin.setMargin(edge, margin)) {
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline const WXCoreMargin &GetMargins() const {
|
||
|
return mCssStyle->mMargin;
|
||
|
}
|
||
|
|
||
|
/** ================================ padding =================================== **/
|
||
|
|
||
|
inline float getPaddingLeft() const {
|
||
|
return mCssStyle->mPadding.getPadding(kPaddingLeft);
|
||
|
}
|
||
|
|
||
|
inline float getPaddingRight() const {
|
||
|
return mCssStyle->mPadding.getPadding(kPaddingRight);
|
||
|
}
|
||
|
|
||
|
inline float getPaddingTop() const {
|
||
|
return mCssStyle->mPadding.getPadding(kPaddingTop);
|
||
|
}
|
||
|
|
||
|
inline float getPaddingBottom() const {
|
||
|
return mCssStyle->mPadding.getPadding(kPaddingBottom);
|
||
|
}
|
||
|
|
||
|
inline void setPadding(const WXCorePaddingEdge edge, const float padding) {
|
||
|
if (mCssStyle->mPadding.setPadding(edge, padding)) {
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline const WXCorePadding &GetPaddings() const {
|
||
|
return mCssStyle->mPadding;
|
||
|
}
|
||
|
|
||
|
/** ================================ border-width =================================== **/
|
||
|
|
||
|
inline float getBorderWidthLeft() const {
|
||
|
return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthLeft);
|
||
|
}
|
||
|
|
||
|
inline float getBorderWidthRight() const {
|
||
|
return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthRight);
|
||
|
}
|
||
|
|
||
|
inline float getBorderWidthTop() const {
|
||
|
return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthTop);
|
||
|
}
|
||
|
|
||
|
inline float getBorderWidthBottom() const {
|
||
|
return mCssStyle->mBorderWidth.getBorderWidth(kBorderWidthBottom);
|
||
|
}
|
||
|
|
||
|
inline void setBorderWidth(const WXCoreBorderWidthEdge edge, const float borderWidth) {
|
||
|
if (mCssStyle->mBorderWidth.setBorderWidth(edge, borderWidth)) {
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline const WXCoreBorderWidth &GetBorders() const {
|
||
|
return mCssStyle->mBorderWidth;
|
||
|
}
|
||
|
|
||
|
/** ================================ position-type =================================== **/
|
||
|
|
||
|
inline void setStylePositionType(const WXCorePositionType positionType) {
|
||
|
if (mCssStyle->mPositionType != positionType) {
|
||
|
mCssStyle->mPositionType = positionType;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCorePositionType getStylePositionType() const {
|
||
|
return mCssStyle->mPositionType;
|
||
|
}
|
||
|
|
||
|
|
||
|
/** ================================ position =================================== **/
|
||
|
|
||
|
inline float getStylePositionTop() const {
|
||
|
return mCssStyle->mStylePosition.getPosition(kPositionEdgeTop);
|
||
|
}
|
||
|
|
||
|
inline float getStylePositionBottom() const {
|
||
|
return mCssStyle->mStylePosition.getPosition(kPositionEdgeBottom);
|
||
|
}
|
||
|
|
||
|
inline float getStylePositionLeft() const {
|
||
|
return mCssStyle->mStylePosition.getPosition(kPositionEdgeLeft);
|
||
|
}
|
||
|
|
||
|
inline float getStylePositionRight() const {
|
||
|
return mCssStyle->mStylePosition.getPosition(kPositionEdgeRight);
|
||
|
}
|
||
|
|
||
|
inline void setStylePosition(const WXCorePositionEdge edge, const float positionRight) {
|
||
|
if (mCssStyle->mStylePosition.setPosition(edge, positionRight))
|
||
|
markDirty();
|
||
|
}
|
||
|
|
||
|
|
||
|
/** ================================ dimension =================================== **/
|
||
|
|
||
|
inline void setStyleWidthLevel(const DimensionLevel level) const {
|
||
|
if (mCssStyle->mStyleWidthLevel != level) {
|
||
|
mCssStyle->mStyleWidthLevel = level;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setStyleHeightLevel(const DimensionLevel level) const {
|
||
|
if (mCssStyle->mStyleHeightLevel != level) {
|
||
|
mCssStyle->mStyleHeightLevel = level;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline DimensionLevel getStyleHeightLevel() const {
|
||
|
return mCssStyle->mStyleHeightLevel;
|
||
|
}
|
||
|
|
||
|
inline DimensionLevel getStyleWidthLevel() const {
|
||
|
return mCssStyle->mStyleWidthLevel;
|
||
|
}
|
||
|
|
||
|
inline void setStyleWidth(const float width, const bool updating) {
|
||
|
if (mCssStyle->mStyleWidth != width) {
|
||
|
mCssStyle->mStyleWidth = width;
|
||
|
markDirty();
|
||
|
if(updating) {
|
||
|
markChildrenDirty(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline void setStyleWidthToNAN() {
|
||
|
if (!isnan(mCssStyle->mStyleWidth)) {
|
||
|
mCssStyle->mStyleWidth = NAN;
|
||
|
markDirty();
|
||
|
markChildrenDirty(true);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getStyleWidth() const {
|
||
|
return mCssStyle->mStyleWidth;
|
||
|
}
|
||
|
|
||
|
inline void setStyleHeight(const float height) {
|
||
|
if (mCssStyle->mStyleHeight != height) {
|
||
|
mCssStyle->mStyleHeight = height;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getStyleHeight() const {
|
||
|
return mCssStyle->mStyleHeight;
|
||
|
}
|
||
|
|
||
|
inline void setMinWidth(const float minWidth, const bool updating) {
|
||
|
if (mCssStyle->mMinWidth != minWidth) {
|
||
|
mCssStyle->mMinWidth = minWidth;
|
||
|
markDirty();
|
||
|
if(updating) {
|
||
|
markChildrenDirty(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getMinWidth() const {
|
||
|
return mCssStyle->mMinWidth;
|
||
|
}
|
||
|
|
||
|
inline void setMaxWidth(const float maxWidth, const bool updating) {
|
||
|
if (mCssStyle->mMaxWidth != maxWidth) {
|
||
|
mCssStyle->mMaxWidth = maxWidth;
|
||
|
markDirty();
|
||
|
if(updating) {
|
||
|
markChildrenDirty(true);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getMaxWidth() const {
|
||
|
return mCssStyle->mMaxWidth;
|
||
|
}
|
||
|
|
||
|
inline void setMinHeight(const float minHeight) {
|
||
|
if (mCssStyle->mMinHeight != minHeight) {
|
||
|
mCssStyle->mMinHeight = minHeight;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getMinHeight() const {
|
||
|
return mCssStyle->mMinHeight;
|
||
|
}
|
||
|
|
||
|
inline void setMaxHeight(const float maxHeight) {
|
||
|
if (mCssStyle->mMaxHeight != maxHeight) {
|
||
|
mCssStyle->mMaxHeight = maxHeight;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getMaxHeight() const {
|
||
|
return mCssStyle->mMaxHeight;
|
||
|
}
|
||
|
|
||
|
inline void setDirection(const WXCoreDirection direction, const bool updating) {
|
||
|
if (nullptr == mCssStyle) return;
|
||
|
|
||
|
if (mCssStyle->mDirection != direction) {
|
||
|
mCssStyle->mDirection = direction;
|
||
|
markDirty();
|
||
|
if (updating) {
|
||
|
for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
|
||
|
(*it)->markInheritableDirty();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreDirection getDirection() const {
|
||
|
if (mCssStyle == nullptr) {
|
||
|
return WEEXCORE_CSS_DEFAULT_DIRECTION;
|
||
|
}
|
||
|
return mCssStyle->mDirection;
|
||
|
}
|
||
|
|
||
|
/** ================================ CSS direction For RTL =================================== **/
|
||
|
|
||
|
void determineChildLayoutDirection(const WXCoreDirection direction);
|
||
|
|
||
|
WXCoreDirection getLayoutDirectionFromPathNode();
|
||
|
|
||
|
/** ================================ flex-style =================================== **/
|
||
|
|
||
|
inline void setFlexDirection(const WXCoreFlexDirection flexDirection, const bool updating) {
|
||
|
if (mCssStyle->mFlexDirection != flexDirection) {
|
||
|
mCssStyle->mFlexDirection = flexDirection;
|
||
|
markDirty();
|
||
|
if (updating) {
|
||
|
for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
|
||
|
(*it)->markDirty(false);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreFlexDirection getFlexDirection() const {
|
||
|
return mCssStyle->mFlexDirection;
|
||
|
}
|
||
|
|
||
|
inline void setFlexWrap(const WXCoreFlexWrap flexWrap) {
|
||
|
if (mCssStyle->mFlexWrap != flexWrap) {
|
||
|
mCssStyle->mFlexWrap = flexWrap;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreFlexWrap getFlexWrap() const {
|
||
|
return mCssStyle->mFlexWrap;
|
||
|
}
|
||
|
|
||
|
inline void setJustifyContent(const WXCoreJustifyContent justifyContent) {
|
||
|
if (mCssStyle->mJustifyContent != justifyContent) {
|
||
|
mCssStyle->mJustifyContent = justifyContent;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreJustifyContent getJustifyContent() const {
|
||
|
return mCssStyle->mJustifyContent;
|
||
|
}
|
||
|
|
||
|
inline void setAlignItems(const WXCoreAlignItems alignItems) {
|
||
|
if (mCssStyle->mAlignItems != alignItems) {
|
||
|
mCssStyle->mAlignItems = alignItems;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreAlignItems getAlignItems() const {
|
||
|
return mCssStyle->mAlignItems;
|
||
|
}
|
||
|
|
||
|
inline void setAlignSelf(const WXCoreAlignSelf alignSelf) {
|
||
|
if (mCssStyle->mAlignSelf != alignSelf) {
|
||
|
mCssStyle->mAlignSelf = alignSelf;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline WXCoreAlignSelf getAlignSelf() const {
|
||
|
return mCssStyle->mAlignSelf;
|
||
|
}
|
||
|
|
||
|
virtual void set_flex(const float flex) {
|
||
|
if (mCssStyle->mFlexGrow != flex) {
|
||
|
mCssStyle->mFlexGrow = flex;
|
||
|
markDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
inline float getFlex() const {
|
||
|
return mCssStyle->mFlexGrow;
|
||
|
}
|
||
|
|
||
|
/** ================================ layout-result =================================== **/
|
||
|
|
||
|
inline float getLayoutWidth() const {
|
||
|
return mLayoutResult->mLayoutSize.width;
|
||
|
}
|
||
|
|
||
|
inline float getLayoutHeight() const {
|
||
|
return mLayoutResult->mLayoutSize.height;
|
||
|
}
|
||
|
|
||
|
inline float getLayoutPositionTop() const {
|
||
|
return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeTop);
|
||
|
}
|
||
|
|
||
|
inline float getLayoutPositionBottom() const {
|
||
|
return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeBottom);
|
||
|
}
|
||
|
|
||
|
inline float getLayoutPositionLeft() const {
|
||
|
return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeLeft);
|
||
|
}
|
||
|
|
||
|
inline float getLayoutPositionRight() const {
|
||
|
return mLayoutResult->mLayoutPosition.getPosition(kPositionEdgeRight);
|
||
|
}
|
||
|
|
||
|
virtual inline WXCoreDirection getLayoutDirection() const {
|
||
|
if (nullptr == mLayoutResult) {
|
||
|
return WEEXCORE_CSS_DEFAULT_DIRECTION;
|
||
|
}
|
||
|
return mLayoutResult->mLayoutDirection;
|
||
|
}
|
||
|
|
||
|
inline void setLayoutDirection(WXCoreDirection direction) {
|
||
|
if (nullptr == mLayoutResult) return;
|
||
|
mLayoutResult->mLayoutDirection = direction;
|
||
|
}
|
||
|
inline bool hasNewLayout() const {
|
||
|
return mHasNewLayout;
|
||
|
}
|
||
|
|
||
|
inline bool isDirty() const {
|
||
|
return dirty;
|
||
|
}
|
||
|
|
||
|
inline void markDirty(const bool recursion = true) {
|
||
|
if (!isDirty()) {
|
||
|
dirty = true;
|
||
|
if (getParent() != nullptr && recursion) {
|
||
|
getParent()->markDirty();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void markAllDirty() {
|
||
|
markDirty(false);
|
||
|
for (WXCoreLayoutNode* c : mChildList) {
|
||
|
c->markAllDirty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool markChildrenDirty(const bool updatedNode = false) {
|
||
|
bool ret = false;
|
||
|
if(getChildCount() == 0){
|
||
|
if(measureFunc!= nullptr){
|
||
|
ret = true;
|
||
|
}
|
||
|
}
|
||
|
else {
|
||
|
//isnan(mCssStyle->mStyleWidth) XOR updatedNode
|
||
|
if(isnan(mCssStyle->mStyleWidth) != updatedNode){
|
||
|
for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
|
||
|
ret = ((*it)->markChildrenDirty() || ret) ;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
dirty = ret || dirty;
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
void markInheritableDirty() {
|
||
|
if (resetInheritableSet()) {
|
||
|
// if some style was inherited from parent, reset those styles
|
||
|
// then mark self dirty
|
||
|
markDirty(false);
|
||
|
|
||
|
// traverse children to mark dirty
|
||
|
if(getChildCount() == 0){
|
||
|
return;
|
||
|
}
|
||
|
else {
|
||
|
for (auto it = ChildListIterBegin(); it != ChildListIterEnd(); it++) {
|
||
|
(*it)->markInheritableDirty();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* if some style was inherited from parent, reset those styles, then return true, eles return false
|
||
|
*/
|
||
|
bool resetInheritableSet() {
|
||
|
if (mCssStyle == nullptr || mLayoutResult == nullptr) return false;
|
||
|
|
||
|
bool hasInheritedStyle = false;
|
||
|
if (mCssStyle->mDirection == kDirectionInherit) {
|
||
|
mLayoutResult->mLayoutDirection = kDirectionInherit;
|
||
|
hasInheritedStyle = true;
|
||
|
}
|
||
|
return hasInheritedStyle;
|
||
|
}
|
||
|
|
||
|
inline void setHasNewLayout(const bool hasNewLayout) {
|
||
|
this->mHasNewLayout = hasNewLayout;
|
||
|
}
|
||
|
|
||
|
inline float getLargestMainSize() const {
|
||
|
float largestSize = 0;
|
||
|
for (WXCoreFlexLine *flexLine : mFlexLines) {
|
||
|
largestSize = std::max(largestSize, flexLine->mMainSize);
|
||
|
}
|
||
|
return largestSize + sumPaddingBorderAlongAxis(this, isMainAxisHorizontal(this));
|
||
|
}
|
||
|
|
||
|
inline void rewriteLayoutResult(float left, float top, float width, float height) {
|
||
|
if (mLayoutResult != nullptr) {
|
||
|
mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeLeft, left);
|
||
|
mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeTop, top);
|
||
|
mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeRight, left + width);
|
||
|
mLayoutResult->mLayoutPosition.setPosition(kPositionEdgeBottom, top + height);
|
||
|
mLayoutResult->mLayoutSize.width = width;
|
||
|
mLayoutResult->mLayoutSize.height = height;
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
#endif //WEEXCORE_FLEXLAYOUT_WXCORELAYOUTNODE_H
|
||
|
#endif
|