diff --git a/React/Base/RCTConvert.h b/React/Base/RCTConvert.h index 35106a694..3d1c4291d 100644 --- a/React/Base/RCTConvert.h +++ b/React/Base/RCTConvert.h @@ -12,6 +12,7 @@ #import "Layout.h" #import "RCTAnimationType.h" +#import "RCTBorderStyle.h" #import "RCTTextDecorationLineType.h" #import "RCTDefines.h" #import "RCTLog.h" @@ -140,6 +141,7 @@ typedef BOOL css_clip_t, css_backface_visibility_t; + (RCTPointerEvents)RCTPointerEvents:(id)json; + (RCTAnimationType)RCTAnimationType:(id)json; ++ (RCTBorderStyle)RCTBorderStyle:(id)json; + (RCTTextDecorationLineType)RCTTextDecorationLineType:(id)json; @end diff --git a/React/Base/RCTConvert.m b/React/Base/RCTConvert.m index 8fc14e102..f5f603343 100644 --- a/React/Base/RCTConvert.m +++ b/React/Base/RCTConvert.m @@ -229,6 +229,12 @@ RCT_ENUM_CONVERTER(NSUnderlineStyle, (@{ @"dashed": @(NSUnderlinePatternDash | NSUnderlineStyleSingle), }), NSUnderlineStyleSingle, integerValue) +RCT_ENUM_CONVERTER(RCTBorderStyle, (@{ + @"solid": @(RCTBorderStyleSolid), + @"dotted": @(RCTBorderStyleDotted), + @"dashed": @(RCTBorderStyleDashed), +}), RCTBorderStyleSolid, integerValue) + RCT_ENUM_CONVERTER(RCTTextDecorationLineType, (@{ @"none": @(RCTTextDecorationLineTypeNone), @"underline": @(RCTTextDecorationLineTypeUnderline), diff --git a/React/React.xcodeproj/project.pbxproj b/React/React.xcodeproj/project.pbxproj index 92b4cf7f6..6d671d58b 100644 --- a/React/React.xcodeproj/project.pbxproj +++ b/React/React.xcodeproj/project.pbxproj @@ -269,6 +269,7 @@ 83CBBACA1A6023D300E9B192 /* RCTConvert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTConvert.h; sourceTree = ""; }; 83CBBACB1A6023D300E9B192 /* RCTConvert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTConvert.m; sourceTree = ""; }; 83F15A171B7CC46900F10295 /* UIView+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+Private.h"; sourceTree = ""; }; + ACDD3FDA1BC7430D00E7DE33 /* RCTBorderStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTBorderStyle.h; sourceTree = ""; }; E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RCTTextDecorationLineType.h; sourceTree = ""; }; E9B20B791B500126007A2DA7 /* RCTAccessibilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTAccessibilityManager.h; sourceTree = ""; }; E9B20B7A1B500126007A2DA7 /* RCTAccessibilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTAccessibilityManager.m; sourceTree = ""; }; @@ -414,6 +415,7 @@ 137327E51AA5CF210034F82E /* RCTTabBarManager.h */, 137327E61AA5CF210034F82E /* RCTTabBarManager.m */, E3BBC8EB1ADE6F47001BBD81 /* RCTTextDecorationLineType.h */, + ACDD3FDA1BC7430D00E7DE33 /* RCTBorderStyle.h */, 13E0674F1A70F44B002CDEE1 /* RCTView.h */, 13E067501A70F44B002CDEE1 /* RCTView.m */, 13442BF41AA90E0B0037E5B0 /* RCTViewControllerProtocol.h */, diff --git a/React/Views/RCTBorderStyle.h b/React/Views/RCTBorderStyle.h new file mode 100644 index 000000000..470d83231 --- /dev/null +++ b/React/Views/RCTBorderStyle.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +#import + +typedef NS_ENUM(NSInteger, RCTBorderStyle) { + RCTBorderStyleUnset = 0, + RCTBorderStyleSolid, + RCTBorderStyleDotted, + RCTBorderStyleDashed, +}; diff --git a/React/Views/RCTView.h b/React/Views/RCTView.h index 1222dc9cf..3f312abd1 100644 --- a/React/Views/RCTView.h +++ b/React/Views/RCTView.h @@ -11,6 +11,7 @@ #import +#import "RCTBorderStyle.h" #import "RCTComponent.h" #import "RCTPointerEvents.h" @@ -84,4 +85,9 @@ @property (nonatomic, assign) CGFloat borderLeftWidth; @property (nonatomic, assign) CGFloat borderWidth; +/** + * Border styles. + */ +@property (nonatomic, assign) RCTBorderStyle borderStyle; + @end diff --git a/React/Views/RCTView.m b/React/Views/RCTView.m index 8f143d8a9..3a3ea7325 100644 --- a/React/Views/RCTView.m +++ b/React/Views/RCTView.m @@ -108,6 +108,7 @@ static NSString *RCTRecursiveAccessibilityLabel(UIView *view) _borderTopRightRadius = -1; _borderBottomLeftRadius = -1; _borderBottomRightRadius = -1; + _borderStyle = RCTBorderStyleSolid; _backgroundColor = super.backgroundColor; } @@ -509,6 +510,7 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused) RCTCornerRadiiAreEqual(cornerRadii) && RCTBorderInsetsAreEqual(borderInsets) && RCTBorderColorsAreEqual(borderColors) && + _borderStyle == RCTBorderStyleSolid && // iOS draws borders in front of the content whereas CSS draws them behind // the content. For this reason, only use iOS border drawing when clipping @@ -531,9 +533,9 @@ RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:unused) return; } - UIImage *image = RCTGetBorderImage([self cornerRadii], - [self bordersAsInsets], - [self borderColors], + UIImage *image = RCTGetBorderImage(cornerRadii, + borderInsets, + borderColors, _backgroundColor.CGColor, self.clipsToBounds); @@ -630,6 +632,8 @@ setBorderWidth(Right) setBorderWidth(Bottom) setBorderWidth(Left) +#pragma mark - Border Radius + #define setBorderRadius(side) \ - (void)setBorder##side##Radius:(CGFloat)radius \ { \ @@ -646,6 +650,20 @@ setBorderRadius(TopRight) setBorderRadius(BottomLeft) setBorderRadius(BottomRight) +#pragma mark - Border Style + +#define setBorderStyle(side) \ + - (void)setBorder##side##Style:(RCTBorderStyle)style \ + { \ + if (_border##side##Style == style) { \ + return; \ + } \ + _border##side##Style = style; \ + [self.layer setNeedsDisplay]; \ + } + +setBorderStyle() + - (void)dealloc { CGColorRelease(_borderColor); diff --git a/React/Views/RCTViewManager.m b/React/Views/RCTViewManager.m index aaac6d279..379adecdc 100644 --- a/React/Views/RCTViewManager.m +++ b/React/Views/RCTViewManager.m @@ -10,6 +10,7 @@ #import "RCTViewManager.h" #import "RCTBridge.h" +#import "RCTBorderStyle.h" #import "RCTConvert.h" #import "RCTEventDispatcher.h" #import "RCTLog.h" @@ -186,6 +187,12 @@ RCT_CUSTOM_VIEW_PROPERTY(borderWidth, CGFloat, RCTView) view.layer.borderWidth = json ? [RCTConvert CGFloat:json] : defaultView.layer.borderWidth; } } +RCT_CUSTOM_VIEW_PROPERTY(borderStyle, RCTBorderStyle, RCTView) +{ + if ([view respondsToSelector:@selector(setBorderStyle:)]) { + view.borderStyle = json ? [RCTConvert RCTBorderStyle:json] : defaultView.borderStyle; + } +} RCT_EXPORT_VIEW_PROPERTY(onAccessibilityTap, RCTDirectEventBlock) RCT_EXPORT_VIEW_PROPERTY(onMagicTap, RCTDirectEventBlock)