zfbool viewIsChildOf(ZF_IN ZFUIView *view, ZF_IN ZFUIView *parentToCheck) { if(view != zfnull) { ZFUIView *tmp = parentToCheck; do { if(tmp == view) { return zftrue; } tmp = tmp->viewParent(); } while(tmp != zfnull); } return zffalse; }
ZF_NAMESPACE_GLOBAL_BEGIN void ZFUIViewLayout::layoutOnMeasure(ZF_OUT ZFUISize &ret, ZF_IN const ZFUISize &sizeHint, ZF_IN const ZFUISizeParam &sizeParam) { ZFUIViewLayoutParam::sizeHintApply(ret, this->viewSizeMin(), sizeHint, sizeParam); for(zfindex i = 0; i < this->childCount(); ++i) { ZFUIView *child = this->childAtIndex(i); ZFUISize sizeHintTmp = sizeHint; if(sizeHintTmp.width >= 0) { sizeHintTmp.width -= ZFUIMarginGetX(child->layoutParam()->layoutMargin()); if(sizeHintTmp.width < 0) { sizeHintTmp.width = 0; } } if(sizeHintTmp.height >= 0) { sizeHintTmp.height -= ZFUIMarginGetY(child->layoutParam()->layoutMargin()); if(sizeHintTmp.height < 0) { sizeHintTmp.height = 0; } } child->layoutMeasure(sizeHintTmp, child->layoutParam()->sizeParam()); ret.width = zfmMax(ret.width, child->layoutMeasuredSize().width + ZFUIMarginGetX(child->layoutParam()->layoutMargin())); ret.height = zfmMax(ret.height, child->layoutMeasuredSize().height + ZFUIMarginGetY(child->layoutParam()->layoutMargin())); } }
static ZFUISize _ZFP_ZFUILinearLayout_measureVertical(ZF_IN ZFUILinearLayout *parent, ZF_IN const ZFUISize &sizeHint, ZF_IN const ZFUISizeParam &sizeParam) { ZFUISize ret = ZFUISizeZero; zfbool hasLayoutedChild = zffalse; zfint parentMarginX = ZFUIMarginGetX(parent->layoutChildMargin()); zfint parentMarginY = ZFUIMarginGetY(parent->layoutChildMargin()); zfint sizeHintLast = -1; do { ret.height = 0; sizeHintLast = -1; for(zfindex i = 0; i < parent->childCount(); ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUILinearLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpace() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); zfint sizeHintTmp = ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(sizeHint.width, -marginX)); if(sizeParam.width == ZFUISizeType::e_Wrap && layoutParam->sizeParam().width == ZFUISizeType::e_Fill) { child->layoutMeasure( ZFUISizeMake(sizeHintTmp, layoutParam->sizeHint().height), ZFUISizeParamWrapWidthWrapHeight); sizeHintTmp = child->layoutMeasuredSize().width; if(sizeHintTmp < ret.width) { sizeHintTmp = ret.width; } if(sizeHintLast == -1) { sizeHintLast = sizeHintTmp; } } child->layoutMeasure( ZFUISizeMake(sizeHintTmp, layoutParam->sizeHint().height), layoutParam->sizeParam()); ret.width = zfmMax(ret.width, child->layoutMeasuredSize().width + marginX); ret.height += prevSpace + child->layoutMeasuredSize().height + marginY; } } while(sizeHintLast != -1 && sizeHintLast != ret.width); return ZFUIViewLayoutParam::sizeHintApply(ret, sizeHint, sizeParam); }
ZFUIView *viewChildAt(ZF_IN ZFUIView *view, ZF_IN const ZFUIPoint &pos, ZF_IN_OPT zfbool filterDisabledView /* = zftrue */, ZF_IN_OPT const ZFFilterForZFObject *filter /* = zfnull */) { if(view == zfnull || (filterDisabledView && !view->viewUIEnableTree()) || (filter != zfnull && !filter->filterCheckActive(view))) { return zfnull; } if(pos.x < 0 || pos.y < 0 || pos.x > view->layoutedFrame().size.width || pos.y > view->layoutedFrame().size.height) { return zfnull; } ZFUIRect layoutedFrameFixed = ZFUIRectZero; ZFCoreArrayPOD<ZFUIView *> childList = view->internalForegroundViewArray(); for(zfindex i = childList.count() - 1; i != zfindexMax; --i) { ZFUIView *child = childList[i]; child->layoutedFrameFixed(layoutedFrameFixed); ZFUIView *tmp = ZFUIViewUtil::viewChildAt(childList[i], ZFUIPointMake( pos.x - layoutedFrameFixed.point.x, pos.y - layoutedFrameFixed.point.y ), filterDisabledView, filter); if(tmp != zfnull) { return tmp; } } childList = view->childArray(); for(zfindex i = childList.count() - 1; i != zfindexMax; --i) { ZFUIView *child = childList[i]; child->layoutedFrameFixed(layoutedFrameFixed); ZFUIView *tmp = ZFUIViewUtil::viewChildAt(childList[i], ZFUIPointMake( pos.x - layoutedFrameFixed.point.x, pos.y - layoutedFrameFixed.point.y ), filter); if(tmp != zfnull) { return tmp; } } childList = view->internalBackgroundViewArray(); for(zfindex i = childList.count() - 1; i != zfindexMax; --i) { ZFUIView *child = childList[i]; child->layoutedFrameFixed(layoutedFrameFixed); ZFUIView *tmp = ZFUIViewUtil::viewChildAt(childList[i], ZFUIPointMake( pos.x - layoutedFrameFixed.point.x, pos.y - layoutedFrameFixed.point.y ), filter); if(tmp != zfnull) { return tmp; } } if(filterDisabledView && !view->viewUIEnable()) { return zfnull; } return view; }
static void _ZFP_ZFUILinearLayout_layoutVertical(ZF_IN ZFUILinearLayout *parent, ZF_IN const ZFUISize &size, ZF_IN zfbool positiveDirection) { zfint requiredSize = 0; zfint totalWeight = 0; zfbool hasLayoutedChild = zffalse; zfint parentMarginX = ZFUIMarginGetX(parent->layoutChildMargin()); zfint parentMarginY = ZFUIMarginGetY(parent->layoutChildMargin()); for(zfindex i = 0; i < parent->childCount(); ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUILinearLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpace() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); if(layoutParam->layoutWeight() > 0) { totalWeight += layoutParam->layoutWeight(); } else { switch(layoutParam->sizeParam().height) { case ZFUISizeType::e_Wrap: { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, -marginX)), layoutParam->sizeHint().height), layoutParam->sizeParam()); requiredSize += child->layoutMeasuredSize().height; } break; case ZFUISizeType::e_Fill: requiredSize = size.height; break; default: zfCoreCriticalShouldNotGoHere(); return ; } } requiredSize += prevSpace + marginY; } hasLayoutedChild = zffalse; zfint flexibleSize = zfmMax(0, size.height - requiredSize); zfint offset = (positiveDirection ? 0 : size.height); for(zfindex i = 0; i < parent->childCount(); ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUILinearLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpace() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); zfint totalUsedSpace = prevSpace + marginY; if(layoutParam->layoutWeight() > 0) { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, -marginX)), ZFUIViewLayoutParam::sizeHintMerge(flexibleSize * layoutParam->layoutWeight() / totalWeight, layoutParam->sizeHint().height) ), ZFUISizeParamMake( layoutParam->sizeParam().width, ZFUISizeType::e_Fill )); flexibleSize -= child->layoutMeasuredSize().height; totalWeight -= layoutParam->layoutWeight(); } else { if(layoutParam->sizeParam().height == ZFUISizeType::e_Fill) { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, -marginX)), ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().height, positiveDirection ? zfmMax(size.height - offset - totalUsedSpace, 0) : zfmMax(offset - totalUsedSpace, 0)) ), layoutParam->sizeParam()); } } if(positiveDirection) { child->layout(ZFUIAlignApply( layoutParam->layoutAlign(), ZFUIRectMake(0, offset + prevSpace, size.width, child->layoutMeasuredSize().height + marginY), child->layoutMeasuredSize(), layoutParam->layoutMargin() + parent->layoutChildMargin())); offset += prevSpace + child->layoutMeasuredSize().height + marginY; } else { offset -= child->layoutMeasuredSize().height + marginY + prevSpace; child->layout(ZFUIAlignApply( layoutParam->layoutAlign(), ZFUIRectMake(0, offset, size.width, child->layoutMeasuredSize().height + marginY), child->layoutMeasuredSize(), layoutParam->layoutMargin() + parent->layoutChildMargin())); } } }
static void _ZFP_ZFUIFlowLayout_layoutVertical(ZF_IN ZFUIFlowLayout *parent, ZF_IN const ZFUISize &size, ZF_IN zfbool positiveDirection) { zfindex wrapIndex = 0; zfint lineSizeUsed = 0; while(wrapIndex < parent->childCount()) // for each line { zfint requiredSize = 0; zfint totalWeight = 0; zfbool hasLayoutedChild = zffalse; zfint parentMarginX = ZFUIMarginGetX(parent->layoutChildMargin()); zfint parentMarginY = ZFUIMarginGetY(parent->layoutChildMargin()); zfindex wrapIndexTmp = parent->childCount(); zfint lineSize = 0; zfint prevLineSpace = (wrapIndex > 0 ? parent->layoutChildSpaceX() : 0); zfint flexableWrapSize = 0; for(zfindex i = wrapIndex; i < parent->childCount(); ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUIFlowLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpaceY() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); zfint childRequiredSize = 0; if(layoutParam->layoutWeight() > 0) { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, 0 - lineSizeUsed - marginX - prevLineSpace)), layoutParam->sizeHint().height), layoutParam->sizeParam()); childRequiredSize += child->layoutMeasuredSize().height; } else { switch(layoutParam->sizeParam().height) { case ZFUISizeType::e_Wrap: child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, 0 - lineSizeUsed - marginX - prevLineSpace)), layoutParam->sizeHint().height), layoutParam->sizeParam()); childRequiredSize += child->layoutMeasuredSize().height; break; case ZFUISizeType::e_Fill: child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, 0 - lineSizeUsed - marginX - prevLineSpace)), layoutParam->sizeHint().height), layoutParam->sizeParam()); childRequiredSize = zfmMax( child->layoutMeasuredSize().height, size.height - requiredSize - prevSpace - marginY); break; default: zfCoreCriticalShouldNotGoHere(); return ; } } childRequiredSize += prevSpace + marginY; if(i > wrapIndex && requiredSize + childRequiredSize > size.height) { wrapIndexTmp = i; break; } if(layoutParam->layoutWeight() > 0) { flexableWrapSize += childRequiredSize; } requiredSize += childRequiredSize; lineSize = zfmMax(lineSize, child->layoutMeasuredSize().width + marginX); if(layoutParam->layoutWeight() > 0) { totalWeight += layoutParam->layoutWeight(); } if(requiredSize >= size.height) { wrapIndexTmp = i + 1; break; } } hasLayoutedChild = zffalse; zfint flexibleSize = zfmMax(0, size.height - requiredSize + flexableWrapSize); zfint offset = (positiveDirection ? 0 : size.height); zfint lineX = ((_ZFP_ZFUIFlowLayout_layoutOrientationSecondary( parent->layoutOrientationMain(), parent->layoutOrientationSecondary()) == ZFUIOrientation::e_Left) ? lineSizeUsed + prevLineSpace : size.width - lineSizeUsed - lineSize - prevLineSpace); for(zfindex i = wrapIndex; i < wrapIndexTmp; ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUIFlowLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpaceY() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); zfint totalUsedSpace = prevSpace + marginY; if(layoutParam->layoutWeight() > 0) { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, 0 - lineSizeUsed - marginX - prevLineSpace)), ZFUIViewLayoutParam::sizeHintMerge(flexibleSize * layoutParam->layoutWeight() / totalWeight, layoutParam->sizeHint().height) ), ZFUISizeParamMake( layoutParam->sizeParam().width, ZFUISizeType::e_Fill )); flexibleSize -= child->layoutMeasuredSize().height; totalWeight -= layoutParam->layoutWeight(); } else { if(layoutParam->sizeParam().height == ZFUISizeType::e_Fill) { child->layoutMeasure( ZFUISizeMake( ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(size.width, 0 - lineSizeUsed - marginX - prevLineSpace)), ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().height, positiveDirection ? zfmMax(size.height - offset - totalUsedSpace, 0) : zfmMax(offset - totalUsedSpace, 0)) ), layoutParam->sizeParam()); } } if(positiveDirection) { child->layout(ZFUIAlignApply( layoutParam->layoutAlign(), ZFUIRectMake(lineX, offset + prevSpace, lineSize, child->layoutMeasuredSize().height + marginY), child->layoutMeasuredSize(), layoutParam->layoutMargin() + parent->layoutChildMargin())); offset += prevSpace + child->layoutMeasuredSize().height + marginY; } else { offset -= child->layoutMeasuredSize().height + marginY + prevSpace; child->layout(ZFUIAlignApply( layoutParam->layoutAlign(), ZFUIRectMake(lineX, offset, lineSize, child->layoutMeasuredSize().height + marginY), child->layoutMeasuredSize(), layoutParam->layoutMargin() + parent->layoutChildMargin())); } } // for(zfindex i = wrapIndex; i < wrapIndexTmp; ++i) wrapIndex = wrapIndexTmp; lineSizeUsed += lineSize + prevLineSpace; } // for each line }
static ZFUISize _ZFP_ZFUIFlowLayout_measureVertical(ZF_IN ZFUIFlowLayout *parent, ZF_IN const ZFUISize &sizeHint, ZF_IN const ZFUISizeParam &sizeParam) { ZFUISize ret = ZFUISizeZero; zfindex wrapIndex = 0; zfint lineSizeUsed = 0; while(wrapIndex < parent->childCount()) // for each line { ZFUISize lineSize = ZFUISizeZero; zfbool hasLayoutedChild = zffalse; zfint parentMarginX = ZFUIMarginGetX(parent->layoutChildMargin()); zfint parentMarginY = ZFUIMarginGetY(parent->layoutChildMargin()); zfint sizeHintLast = -1; zfindex wrapIndexTmp = -1; zfint prevLineSpace = (wrapIndex ? parent->layoutChildSpaceX() : 0); do { lineSize.height = 0; sizeHintLast = -1; wrapIndexTmp = parent->childCount(); for(zfindex i = wrapIndex; i < parent->childCount(); ++i) { ZFUIView *child = parent->childAtIndex(i); ZFUIFlowLayoutParam *layoutParam = child->layoutParamT(); if(!child->viewVisible() && !layoutParam->layoutReserveSpaceWhenNotVisible()) { continue ; } zfint prevSpace = (hasLayoutedChild ? parent->layoutChildSpaceY() : 0); hasLayoutedChild = zftrue; zfint marginX = parentMarginX + ZFUIMarginGetX(layoutParam->layoutMargin()); zfint marginY = parentMarginY + ZFUIMarginGetY(layoutParam->layoutMargin()); zfint sizeHintTmp = ZFUIViewLayoutParam::sizeHintMerge( layoutParam->sizeHint().width, ZFUIViewLayoutParam::sizeHintOffset(sizeHint.width, 0 - lineSizeUsed - marginX - prevLineSpace)); if(sizeParam.width == ZFUISizeType::e_Wrap && layoutParam->sizeParam().width == ZFUISizeType::e_Fill) { child->layoutMeasure( ZFUISizeMake(sizeHintTmp, layoutParam->sizeHint().height), ZFUISizeParamWrapWidthWrapHeight); sizeHintTmp = child->layoutMeasuredSize().width; if(sizeHintTmp < lineSize.width) { sizeHintTmp = lineSize.width; } if(sizeHintLast == -1) { sizeHintLast = sizeHintTmp; } } child->layoutMeasure( ZFUISizeMake(sizeHintTmp, layoutParam->sizeHint().height), layoutParam->sizeParam()); if(i > wrapIndex && sizeHint.height >= 0 && lineSize.height + prevSpace + child->layoutMeasuredSize().height + marginY > sizeHint.height) { wrapIndexTmp = i; break; } lineSize.height += prevSpace + child->layoutMeasuredSize().height + marginY; lineSize.width = zfmMax(lineSize.width, child->layoutMeasuredSize().width + marginX + prevLineSpace); if(layoutParam->sizeParam().height == ZFUISizeType::e_Fill || (sizeHint.height >= 0 && lineSize.height == sizeHint.height)) { wrapIndexTmp = i + 1; break; } } } while(sizeHintLast != -1 && sizeHintLast != lineSize.width); lineSizeUsed += lineSize.width; wrapIndex = wrapIndexTmp; ret.height = zfmMax(ret.height, lineSize.height); ret.width += lineSize.width; } // for each line return ret; }