181 lines
5.8 KiB
Objective-C
181 lines
5.8 KiB
Objective-C
#import "RNCSafeAreaShadowView.h"
|
|
|
|
#import <React/RCTAssert.h>
|
|
#include <math.h>
|
|
|
|
#import "RNCSafeAreaViewLocalData.h"
|
|
#import "RNCSafeAreaViewMode.h"
|
|
#import "RNCSafeAreaViewEdges.h"
|
|
|
|
// From RCTShadowView.m
|
|
typedef NS_ENUM(unsigned int, meta_prop_t) {
|
|
META_PROP_LEFT,
|
|
META_PROP_TOP,
|
|
META_PROP_RIGHT,
|
|
META_PROP_BOTTOM,
|
|
META_PROP_HORIZONTAL,
|
|
META_PROP_VERTICAL,
|
|
META_PROP_ALL,
|
|
META_PROP_COUNT,
|
|
};
|
|
|
|
@implementation RNCSafeAreaShadowView {
|
|
RNCSafeAreaViewLocalData *_localData;
|
|
bool _needsUpdate;
|
|
YGValue _paddingMetaProps[META_PROP_COUNT];
|
|
YGValue _marginMetaProps[META_PROP_COUNT];
|
|
}
|
|
|
|
- (instancetype)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
_needsUpdate = false;
|
|
for (unsigned int ii = 0; ii < META_PROP_COUNT; ii++) {
|
|
_paddingMetaProps[ii] = YGValueUndefined;
|
|
_marginMetaProps[ii] = YGValueUndefined;
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)extractEdges:(YGValue[])_metaProps top:(CGFloat *)top right:(CGFloat *)right bottom:(CGFloat *)bottom left:(CGFloat *)left
|
|
{
|
|
if (_metaProps[META_PROP_ALL].unit == YGUnitPoint) {
|
|
*top = _metaProps[META_PROP_ALL].value;
|
|
*right = _metaProps[META_PROP_ALL].value;
|
|
*bottom = _metaProps[META_PROP_ALL].value;
|
|
*left = _metaProps[META_PROP_ALL].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_HORIZONTAL].unit == YGUnitPoint) {
|
|
*right = _metaProps[META_PROP_HORIZONTAL].value;
|
|
*left = _metaProps[META_PROP_HORIZONTAL].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_VERTICAL].unit == YGUnitPoint) {
|
|
*top = _metaProps[META_PROP_VERTICAL].value;
|
|
*bottom = _metaProps[META_PROP_VERTICAL].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_TOP].unit == YGUnitPoint) {
|
|
*top = _metaProps[META_PROP_TOP].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_RIGHT].unit == YGUnitPoint) {
|
|
*right = _metaProps[META_PROP_RIGHT].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_BOTTOM].unit == YGUnitPoint) {
|
|
*bottom = _metaProps[META_PROP_BOTTOM].value;
|
|
}
|
|
|
|
if (_metaProps[META_PROP_LEFT].unit == YGUnitPoint) {
|
|
*left = _metaProps[META_PROP_LEFT].value;
|
|
}
|
|
}
|
|
|
|
- (void)resetInsetsForMode:(RNCSafeAreaViewMode)mode {
|
|
if (mode == RNCSafeAreaViewModePadding) {
|
|
super.paddingTop = _paddingMetaProps[META_PROP_TOP];
|
|
super.paddingRight = _paddingMetaProps[META_PROP_RIGHT];
|
|
super.paddingBottom = _paddingMetaProps[META_PROP_BOTTOM];
|
|
super.paddingLeft = _paddingMetaProps[META_PROP_LEFT];
|
|
} else if (mode == RNCSafeAreaViewModeMargin) {
|
|
super.marginTop = _marginMetaProps[META_PROP_TOP];
|
|
super.marginRight = _marginMetaProps[META_PROP_RIGHT];
|
|
super.marginBottom = _marginMetaProps[META_PROP_BOTTOM];
|
|
super.marginLeft = _marginMetaProps[META_PROP_LEFT];
|
|
}
|
|
}
|
|
|
|
- (void)updateInsets
|
|
{
|
|
if (_localData == nil) {
|
|
return;
|
|
}
|
|
|
|
UIEdgeInsets insets = _localData.insets;
|
|
RNCSafeAreaViewMode mode = _localData.mode;
|
|
RNCSafeAreaViewEdges edges = _localData.edges;
|
|
|
|
CGFloat top = 0;
|
|
CGFloat right = 0;
|
|
CGFloat bottom = 0;
|
|
CGFloat left = 0;
|
|
|
|
CGFloat insetTop = (edges & RNCSafeAreaViewEdgesTop) ? insets.top : 0;
|
|
CGFloat insetRight = (edges & RNCSafeAreaViewEdgesRight) ? insets.right : 0;
|
|
CGFloat insetBottom = (edges & RNCSafeAreaViewEdgesBottom) ? insets.bottom : 0;
|
|
CGFloat insetLeft = (edges & RNCSafeAreaViewEdgesLeft) ? insets.left : 0;
|
|
|
|
if (mode == RNCSafeAreaViewModePadding) {
|
|
[self extractEdges:_paddingMetaProps top:&top right:&right bottom:&bottom left:&left];
|
|
super.paddingTop = (YGValue){insetTop + top, YGUnitPoint};
|
|
super.paddingRight = (YGValue){insetRight + right, YGUnitPoint};
|
|
super.paddingBottom = (YGValue){insetBottom + bottom, YGUnitPoint};
|
|
super.paddingLeft = (YGValue){insetLeft + left, YGUnitPoint};
|
|
} else if (mode == RNCSafeAreaViewModeMargin) {
|
|
[self extractEdges:_marginMetaProps top:&top right:&right bottom:&bottom left:&left];
|
|
super.marginTop = (YGValue){insetTop + top, YGUnitPoint};
|
|
super.marginRight = (YGValue){insetRight + right, YGUnitPoint};
|
|
super.marginBottom = (YGValue){insetBottom + bottom, YGUnitPoint};
|
|
super.marginLeft = (YGValue){insetLeft + left, YGUnitPoint};
|
|
}
|
|
}
|
|
|
|
- (void)didSetProps:(NSArray<NSString *> *)changedProps
|
|
{
|
|
if (_needsUpdate) {
|
|
_needsUpdate = false;
|
|
[self updateInsets];
|
|
}
|
|
[super didSetProps:changedProps];
|
|
}
|
|
|
|
- (void)setLocalData:(RNCSafeAreaViewLocalData *)localData
|
|
{
|
|
RCTAssert(
|
|
[localData isKindOfClass:[RNCSafeAreaViewLocalData class]],
|
|
@"Local data object for `RCTRNCSafeAreaShadowView` must be `RCTRNCSafeAreaViewLocalData` instance."
|
|
);
|
|
|
|
if (_localData != nil && _localData.mode != localData.mode) {
|
|
[self resetInsetsForMode:_localData.mode];
|
|
}
|
|
|
|
_localData = localData;
|
|
_needsUpdate = false;
|
|
[self updateInsets];
|
|
|
|
if (_localData.mode == RNCSafeAreaViewModePadding) {
|
|
[super didSetProps:@[@"paddingTop", @"paddingRight", @"paddingBottom", @"paddingLeft"]];
|
|
} else {
|
|
[super didSetProps:@[@"marginTop", @"marginRight", @"marginBottom", @"marginLeft"]];
|
|
}
|
|
}
|
|
|
|
#define SHADOW_VIEW_MARGIN_PADDING_PROP(edge, metaProp) \
|
|
- (void)setPadding##edge:(YGValue)value \
|
|
{ \
|
|
[super setPadding##edge:value]; \
|
|
_needsUpdate = true; \
|
|
_paddingMetaProps[META_PROP_##metaProp] = value; \
|
|
} \
|
|
- (void)setMargin##edge:(YGValue)value \
|
|
{ \
|
|
[super setMargin##edge:value]; \
|
|
_needsUpdate = true; \
|
|
_marginMetaProps[META_PROP_##metaProp] = value; \
|
|
}
|
|
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(, ALL);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Vertical, VERTICAL);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Horizontal, HORIZONTAL);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Top, TOP);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Right, RIGHT);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Bottom, BOTTOM);
|
|
SHADOW_VIEW_MARGIN_PADDING_PROP(Left, LEFT);
|
|
|
|
@end
|