├── .gitattributes ├── .gitignore ├── BSStackView.podspec ├── BSStackView ├── BSStackView.h ├── BSStackView.m ├── BSStackViewConstraints.h ├── BSStackViewConstraints.m ├── BSStackViewLayoutHelper.h ├── BSStackViewLayoutHelper.m ├── BSStackViewProtocol.h └── Weakify │ ├── EXTScope.h │ ├── EXTScope.m │ └── metamacros.h ├── DemoResources └── demo.gif ├── Example ├── BSStackView_Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── BSStackView_Example │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m └── podfile ├── LICENSE ├── README.md └── _config.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | BSStackView/Weakify/* linguist-vendored 2 | *.h linguist-language=Objective-C 3 | *.m linguist-language=Objective-C -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /BSStackView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | spec.name = 'BSStackView' 3 | spec.version = '1.0.0' 4 | spec.license = { :type => 'MIT', :file => 'LICENSE' } 5 | spec.homepage = 'https://github.com/iBlacksus/BSStackView' 6 | spec.authors = { 'iBlacksus' => 'iblacksus@gmail.com' } 7 | spec.summary = 'StackView like card interface' 8 | spec.source = { :git => 'https://github.com/iBlacksus/BSStackView.git', :tag => '1.0.0' } 9 | spec.source_files = 'BSStackView/**/*' 10 | spec.framework = 'SystemConfiguration' 11 | spec.ios.deployment_target = '8.0' 12 | spec.ios.framework = 'UIKit' 13 | end -------------------------------------------------------------------------------- /BSStackView/BSStackView.h: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackView.h 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/10/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "BSStackViewConstraints.h" 11 | #import "BSStackViewProtocol.h" 12 | 13 | @interface BSStackView : UIView 14 | 15 | @property (assign, nonatomic) UISwipeGestureRecognizerDirection swipeDirections; 16 | @property (assign, nonatomic) UISwipeGestureRecognizerDirection forwardDirections; 17 | @property (assign, nonatomic) UISwipeGestureRecognizerDirection backwardDirections; 18 | @property (strong, nonatomic, readonly) BSStackViewConstraints *contraintsConfigurator; 19 | @property (assign, nonatomic) CGFloat animationDuration; 20 | @property (assign, nonatomic) BOOL changeAlphaOnSendAnimation; 21 | @property (weak, nonatomic) id delegate; 22 | 23 | - (void)configureWithViews:(NSArray *)views; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /BSStackView/BSStackView.m: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackView.m 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/10/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import "BSStackView.h" 10 | #import "EXTScope.h" 11 | #import "BSStackViewLayoutHelper.h" 12 | 13 | static CGFloat const BSStackViewMinAlpha = .9; 14 | static CGFloat const BSStackViewMinBackgroundWhite = .7; 15 | static CGFloat const BSStackViewAnimationDurationDefault = .25; 16 | 17 | @interface BSStackView () 18 | 19 | @property (copy, nonatomic) NSArray *views; 20 | @property (strong, nonatomic) NSMutableDictionary *viewConstraints; 21 | @property (copy, nonatomic) NSArray *gestures; 22 | @property (assign, nonatomic) UIView *dontUpdateItem; 23 | 24 | @end 25 | 26 | @implementation BSStackView 27 | 28 | #pragma mark - Accessors - 29 | 30 | - (void)setSwipeDirections:(UISwipeGestureRecognizerDirection)swipeDirections { 31 | _swipeDirections = swipeDirections; 32 | 33 | NSMutableArray *gestures = [NSMutableArray array]; 34 | 35 | if (swipeDirections & UISwipeGestureRecognizerDirectionLeft) { 36 | [gestures addObject:[self addSwipeWithDirection:UISwipeGestureRecognizerDirectionLeft]]; 37 | } 38 | 39 | if (swipeDirections & UISwipeGestureRecognizerDirectionUp) { 40 | [gestures addObject:[self addSwipeWithDirection:UISwipeGestureRecognizerDirectionUp]]; 41 | } 42 | 43 | if (swipeDirections & UISwipeGestureRecognizerDirectionRight) { 44 | [gestures addObject:[self addSwipeWithDirection:UISwipeGestureRecognizerDirectionRight]]; 45 | } 46 | 47 | if (swipeDirections & UISwipeGestureRecognizerDirectionDown) { 48 | [gestures addObject:[self addSwipeWithDirection:UISwipeGestureRecognizerDirectionDown]]; 49 | } 50 | 51 | self.gestures = gestures; 52 | 53 | [self enableGestures:self.views.count > 0]; 54 | } 55 | 56 | #pragma mark - Life cycle - 57 | 58 | - (instancetype)initWithCoder:(NSCoder *)aDecoder { 59 | if (self = [super initWithCoder:aDecoder]) { 60 | [self initialize]; 61 | } 62 | 63 | return self; 64 | } 65 | 66 | #pragma mark - Initialization - 67 | 68 | - (void)initialize { 69 | _viewConstraints = [NSMutableDictionary dictionary]; 70 | _gestures = @[]; 71 | _contraintsConfigurator = [[BSStackViewConstraints alloc] init]; 72 | _animationDuration = BSStackViewAnimationDurationDefault; 73 | } 74 | 75 | #pragma mark - Public - 76 | 77 | - (void)configureWithViews:(NSArray *)views { 78 | [self removeAllViews]; 79 | 80 | self.views = views; 81 | 82 | [self enableGestures:views.count > 0]; 83 | [self removeAllConstraints]; 84 | 85 | NSInteger index = 0; 86 | for (UIView *view in views) { 87 | [view setTranslatesAutoresizingMaskIntoConstraints:NO]; 88 | view.tag = index; 89 | view.layer.cornerRadius = 5.; 90 | view.layer.masksToBounds = YES; 91 | [self addSubview:view]; 92 | [self sendSubviewToBack:view]; 93 | 94 | index++; 95 | } 96 | 97 | [self updateViews]; 98 | } 99 | 100 | #pragma mark - Private - 101 | 102 | - (void)removeAllViews { 103 | for (UIView *view in self.views) { 104 | [view removeFromSuperview]; 105 | } 106 | } 107 | 108 | - (void)enableGestures:(BOOL)enable { 109 | for (UIGestureRecognizer *gesture in self.gestures) { 110 | gesture.enabled = enable; 111 | } 112 | } 113 | 114 | - (void)removeAllConstraints { 115 | for (NSArray *constraints in self.viewConstraints) { 116 | [self removeConstraints:constraints]; 117 | } 118 | } 119 | 120 | - (UISwipeGestureRecognizer *)addSwipeWithDirection:(UISwipeGestureRecognizerDirection)direction { 121 | UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipe:)]; 122 | swipeGesture.direction = direction; 123 | [self addGestureRecognizer:swipeGesture]; 124 | 125 | return swipeGesture; 126 | } 127 | 128 | - (void)updateViews { 129 | for (NSInteger i = 0; i < self.views.count; i++) { 130 | [self updateViewAtIndex:i]; 131 | } 132 | } 133 | 134 | - (void)updateViewAtIndex:(NSInteger)index { 135 | if (index >= self.views.count) { 136 | return; 137 | } 138 | 139 | UIView *view = self.views[index]; 140 | if (self.dontUpdateItem == view) { 141 | return; 142 | } 143 | 144 | NSArray *oldConstraints = self.viewConstraints[@(view.tag)]; 145 | view.alpha = [self calculateAlphaForIndex:index]; 146 | view.backgroundColor = [UIColor colorWithWhite:[self calculateBackgroundWhiteForIndex:index] alpha:1.]; 147 | 148 | NSArray *contraints = [self.contraintsConfigurator constraintsForView:view index:index]; 149 | [self removeConstraints:oldConstraints]; 150 | [self addConstraints:contraints]; 151 | self.viewConstraints[@(view.tag)] = contraints; 152 | } 153 | 154 | - (CGFloat)calculateAlphaForIndex:(NSInteger)index { 155 | return (1. - BSStackViewMinAlpha) / self.views.count * (self.views.count - index) + BSStackViewMinAlpha; 156 | } 157 | 158 | - (CGFloat)calculateBackgroundWhiteForIndex:(NSInteger)index { 159 | return (1. - BSStackViewMinBackgroundWhite) / self.views.count * (self.views.count - index) + BSStackViewMinBackgroundWhite; 160 | } 161 | 162 | - (void)sendView:(UIView *)view direction:(UISwipeGestureRecognizerDirection)direction { 163 | NSMutableArray *constraints = [NSMutableArray arrayWithArray:self.viewConstraints[@(view.tag)]]; 164 | BOOL forward = [self isForwardDirection:direction]; 165 | 166 | NSLayoutAttribute attribute = [BSStackViewLayoutHelper layoutAttributeForDirection:direction]; 167 | NSLayoutAttribute invertAttribute = [BSStackViewLayoutHelper invertLayoutAttribute:attribute]; 168 | BOOL isVertical = [BSStackViewLayoutHelper isVerticalAttribute:attribute]; 169 | CGFloat x = isVertical ? CGRectGetHeight(self.frame) : CGRectGetWidth(self.frame); 170 | NSMutableArray *oldConstraints = [NSMutableArray array]; 171 | CGFloat firstConstraint = 0.; 172 | CGFloat secondConstraint = 0.; 173 | 174 | for (NSLayoutConstraint *constraint in constraints) { 175 | if ([BSStackViewLayoutHelper isConstraint:constraint hasAttribute:attribute forItem:self]) { 176 | [oldConstraints addObject:constraint]; 177 | firstConstraint = forward ? constraint.constant - x : constraint.constant + x; 178 | 179 | } else if ([BSStackViewLayoutHelper isConstraint:constraint hasAttribute:invertAttribute forItem:self]) { 180 | [oldConstraints addObject:constraint]; 181 | secondConstraint = forward ? constraint.constant + x : constraint.constant - x; 182 | } 183 | } 184 | 185 | [self removeConstraints:oldConstraints]; 186 | [constraints removeObjectsInArray:oldConstraints]; 187 | NSArray *newConstraints = @[]; 188 | 189 | if (isVertical) { 190 | CGFloat top = attribute == NSLayoutAttributeTop ? firstConstraint : secondConstraint; 191 | CGFloat bottom = attribute == NSLayoutAttributeBottom ? firstConstraint : secondConstraint; 192 | newConstraints = [self.contraintsConfigurator verticalConstraintsForView:view top:top bottom:bottom]; 193 | } else { 194 | CGFloat leading = attribute == NSLayoutAttributeLeading ? firstConstraint : secondConstraint; 195 | CGFloat trailing = attribute == NSLayoutAttributeTrailing ? firstConstraint : secondConstraint; 196 | newConstraints = [self.contraintsConfigurator horizontalConstraintsForView:view leading:leading trailing:trailing]; 197 | } 198 | 199 | [self addConstraints:newConstraints]; 200 | [constraints addObjectsFromArray:newConstraints]; 201 | self.viewConstraints[@(view.tag)] = constraints; 202 | } 203 | 204 | - (void)sendViewAnimationCompletion:(UISwipeGestureRecognizerDirection)direction { 205 | self.dontUpdateItem = nil; 206 | BOOL forward = [self isForwardDirection:direction]; 207 | UIView *view = forward ? self.views.lastObject : self.views.firstObject; 208 | NSInteger index = forward ? self.views.count - 1 : 0; 209 | [self updateViewAtIndex:index]; 210 | if (self.changeAlphaOnSendAnimation) { 211 | view.alpha = 0.; 212 | } 213 | 214 | if (forward) { 215 | [self sendSubviewToBack:view]; 216 | } else { 217 | [self bringSubviewToFront:view]; 218 | } 219 | 220 | @weakify(self); 221 | [UIView animateWithDuration:self.animationDuration animations:^{ 222 | @strongify(self); 223 | if (self.changeAlphaOnSendAnimation) { 224 | view.alpha = [self calculateAlphaForIndex:index]; 225 | } 226 | [self layoutIfNeeded]; 227 | } completion:^(BOOL finished) { 228 | @strongify(self); 229 | if (self.delegate && [self.delegate respondsToSelector:@selector(stackView:didSendItem:direction:)]) { 230 | BSStackViewItemDirection direction = forward ? BSStackViewItemDirectionBack : BSStackViewItemDirectionFront; 231 | [self.delegate stackView:self didSendItem:view direction:direction]; 232 | } 233 | }]; 234 | } 235 | 236 | #pragma mark - Gestures - 237 | 238 | - (void)checkDirections { 239 | if (self.forwardDirections == 0 && self.backwardDirections == 0) { 240 | self.forwardDirections = self.swipeDirections; 241 | } 242 | } 243 | 244 | - (BOOL)isForwardDirection:(UISwipeGestureRecognizerDirection)direction { 245 | return direction & self.forwardDirections; 246 | } 247 | 248 | - (void)swipe:(UISwipeGestureRecognizer *)gesture { 249 | [self checkDirections]; 250 | BOOL forward = [self isForwardDirection:gesture.direction]; 251 | UIView *view = forward ? self.views.firstObject : self.views.lastObject; 252 | 253 | if (self.delegate && [self.delegate respondsToSelector:@selector(stackView:willSendItem:direction:)]) { 254 | BSStackViewItemDirection direction = forward ? BSStackViewItemDirectionBack : BSStackViewItemDirectionFront; 255 | [self.delegate stackView:self willSendItem:view direction:direction]; 256 | } 257 | 258 | [self sendView:view direction:gesture.direction]; 259 | 260 | NSMutableArray *views = self.views.mutableCopy; 261 | [views removeObject:view]; 262 | if (forward) { 263 | [views addObject:view]; 264 | } else { 265 | [views insertObject:view atIndex:0]; 266 | } 267 | 268 | self.views = views; 269 | 270 | self.dontUpdateItem = view; 271 | [self updateViews]; 272 | 273 | @weakify(self); 274 | [UIView animateWithDuration:self.animationDuration animations:^{ 275 | @strongify(self); 276 | if (self.changeAlphaOnSendAnimation) { 277 | view.alpha = 0.; 278 | } 279 | [self layoutIfNeeded]; 280 | } completion:^(BOOL finished) { 281 | @strongify(self); 282 | [self sendViewAnimationCompletion:gesture.direction]; 283 | }]; 284 | } 285 | 286 | @end 287 | -------------------------------------------------------------------------------- /BSStackView/BSStackViewConstraints.h: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackViewConstraints.h 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BSStackViewConstraints : NSObject 12 | 13 | @property (nonatomic, assign) CGFloat leading; 14 | @property (nonatomic, assign) CGFloat trailing; 15 | @property (nonatomic, assign) CGFloat top; 16 | @property (nonatomic, assign) CGFloat bottom; 17 | @property (nonatomic, assign) CGFloat verticalCompression; 18 | @property (nonatomic, assign) CGFloat horizontalCompression; 19 | 20 | - (instancetype)init; 21 | 22 | - (NSArray *)constraintsForView:(UIView *)view index:(NSInteger)index; 23 | - (NSArray *)horizontalConstraintsForView:(UIView *)view index:(NSInteger)index; 24 | - (NSArray *)horizontalConstraintsForView:(UIView *)view leading:(CGFloat)leading trailing:(CGFloat)trailing; 25 | - (NSArray *)verticalConstraintsForView:(UIView *)view index:(NSInteger)index; 26 | - (NSArray *)verticalConstraintsForView:(UIView *)view top:(CGFloat)top bottom:(CGFloat)bottom; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /BSStackView/BSStackViewConstraints.m: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackViewConstraints.m 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import "BSStackViewConstraints.h" 10 | 11 | static CGFloat const BSStackViewConstraintsLeadingDefault = 40.; 12 | static CGFloat const BSStackViewConstraintsTrailingDefault = 40.; 13 | static CGFloat const BSStackViewConstraintsTopDefault = 100.; 14 | static CGFloat const BSStackViewConstraintsBottomDefault = 140.; 15 | static CGFloat const BSStackViewConstraintsCompressionHorizontalDefault = 10.; 16 | static CGFloat const BSStackViewConstraintsCompressionVerticalDefault = 10.; 17 | 18 | @implementation BSStackViewConstraints 19 | 20 | - (instancetype)init { 21 | if (self = [super init]) { 22 | _leading = BSStackViewConstraintsLeadingDefault; 23 | _trailing = BSStackViewConstraintsTrailingDefault; 24 | _top = BSStackViewConstraintsTopDefault; 25 | _bottom = BSStackViewConstraintsBottomDefault; 26 | _verticalCompression = BSStackViewConstraintsCompressionVerticalDefault; 27 | _horizontalCompression = BSStackViewConstraintsCompressionHorizontalDefault; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (NSArray *)constraintsForView:(UIView *)view index:(NSInteger)index { 34 | NSMutableArray *contraints = [NSMutableArray array]; 35 | [contraints addObjectsFromArray:[self horizontalConstraintsForView:view index:index]]; 36 | [contraints addObjectsFromArray:[self verticalConstraintsForView:view index:index]]; 37 | 38 | return contraints; 39 | } 40 | 41 | - (NSArray *)horizontalConstraintsForView:(UIView *)view index:(NSInteger)index { 42 | CGFloat leading = self.leading + self.horizontalCompression * index; 43 | CGFloat trailing = self.trailing + self.horizontalCompression * index; 44 | 45 | return [self horizontalConstraintsForView:view leading:leading trailing:trailing]; 46 | } 47 | 48 | - (NSArray *)horizontalConstraintsForView:(UIView *)view leading:(CGFloat)leading trailing:(CGFloat)trailing { 49 | NSDictionary *views = NSDictionaryOfVariableBindings(view); 50 | NSString *format = [NSString stringWithFormat:@"H:|-(%.f)-[view]-(%.f)-|", leading, trailing]; 51 | 52 | return [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 53 | } 54 | 55 | - (NSArray *)verticalConstraintsForView:(UIView *)view index:(NSInteger)index { 56 | CGFloat top = self.top + self.verticalCompression * index; 57 | CGFloat bottom = self.bottom - self.verticalCompression * index; 58 | 59 | return [self verticalConstraintsForView:view top:top bottom:bottom]; 60 | } 61 | 62 | - (NSArray *)verticalConstraintsForView:(UIView *)view top:(CGFloat)top bottom:(CGFloat)bottom { 63 | NSDictionary *views = NSDictionaryOfVariableBindings(view); 64 | NSString *format = [NSString stringWithFormat:@"V:|-(%.f)-[view]-(%.f)-|", top, bottom]; 65 | 66 | return [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:views]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /BSStackView/BSStackViewLayoutHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackViewLayoutHelper.h 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface BSStackViewLayoutHelper : NSObject 12 | 13 | + (NSLayoutAttribute)layoutAttributeForDirection:(UISwipeGestureRecognizerDirection)direction; 14 | + (NSLayoutAttribute)invertLayoutAttribute:(NSLayoutAttribute)attribute; 15 | + (BOOL)isConstraint:(NSLayoutConstraint *)constraint hasAttribute:(NSLayoutAttribute)attribute forItem:(id)item; 16 | + (BOOL)isVerticalAttribute:(NSLayoutAttribute)attribute; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /BSStackView/BSStackViewLayoutHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackViewLayoutHelper.m 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import "BSStackViewLayoutHelper.h" 10 | 11 | @implementation BSStackViewLayoutHelper 12 | 13 | 14 | + (NSLayoutAttribute)layoutAttributeForDirection:(UISwipeGestureRecognizerDirection)direction { 15 | switch (direction) { 16 | case UISwipeGestureRecognizerDirectionLeft: 17 | return NSLayoutAttributeLeading; 18 | 19 | case UISwipeGestureRecognizerDirectionUp: 20 | return NSLayoutAttributeTop; 21 | 22 | case UISwipeGestureRecognizerDirectionRight: 23 | return NSLayoutAttributeTrailing; 24 | 25 | case UISwipeGestureRecognizerDirectionDown: 26 | return NSLayoutAttributeBottom; 27 | } 28 | } 29 | 30 | + (NSLayoutAttribute)invertLayoutAttribute:(NSLayoutAttribute)attribute { 31 | switch (attribute) { 32 | case NSLayoutAttributeLeading: 33 | return NSLayoutAttributeTrailing; 34 | 35 | case NSLayoutAttributeTop: 36 | return NSLayoutAttributeBottom; 37 | 38 | case NSLayoutAttributeTrailing: 39 | return NSLayoutAttributeLeading; 40 | 41 | case NSLayoutAttributeBottom: 42 | return NSLayoutAttributeTop; 43 | 44 | default: 45 | return NSLayoutAttributeTop; 46 | } 47 | } 48 | 49 | + (BOOL)isConstraint:(NSLayoutConstraint *)constraint hasAttribute:(NSLayoutAttribute)attribute forItem:(id)item { 50 | return (constraint.firstItem == item && constraint.firstAttribute == attribute) || 51 | (constraint.secondItem == item && constraint.secondAttribute == attribute); 52 | } 53 | 54 | + (BOOL)isVerticalAttribute:(NSLayoutAttribute)attribute { 55 | switch (attribute) { 56 | case NSLayoutAttributeLeading: 57 | case NSLayoutAttributeTrailing: 58 | return NO; 59 | 60 | case NSLayoutAttributeTop: 61 | case NSLayoutAttributeBottom: 62 | return YES; 63 | 64 | default: 65 | return NO; 66 | } 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /BSStackView/BSStackViewProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // BSStackViewProtocol.h 3 | // stack 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | @class BSStackView; 11 | 12 | typedef NS_ENUM(NSInteger, BSStackViewItemDirection) { 13 | BSStackViewItemDirectionBack, 14 | BSStackViewItemDirectionFront 15 | }; 16 | 17 | @protocol BSStackViewProtocol 18 | @optional 19 | 20 | - (void)stackView:(BSStackView *)stackView willSendItem:(UIView *)item direction:(BSStackViewItemDirection)direction; 21 | - (void)stackView:(BSStackView *)stackView didSendItem:(UIView *)item direction:(BSStackViewItemDirection)direction; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /BSStackView/Weakify/EXTScope.h: -------------------------------------------------------------------------------- 1 | // 2 | // EXTScope.h 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-05-04. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "metamacros.h" 11 | 12 | /** 13 | * \@onExit defines some code to be executed when the current scope exits. The 14 | * code must be enclosed in braces and terminated with a semicolon, and will be 15 | * executed regardless of how the scope is exited, including from exceptions, 16 | * \c goto, \c return, \c break, and \c continue. 17 | * 18 | * Provided code will go into a block to be executed later. Keep this in mind as 19 | * it pertains to memory management, restrictions on assignment, etc. Because 20 | * the code is used within a block, \c return is a legal (though perhaps 21 | * confusing) way to exit the cleanup block early. 22 | * 23 | * Multiple \@onExit statements in the same scope are executed in reverse 24 | * lexical order. This helps when pairing resource acquisition with \@onExit 25 | * statements, as it guarantees teardown in the opposite order of acquisition. 26 | * 27 | * @note This statement cannot be used within scopes defined without braces 28 | * (like a one line \c if). In practice, this is not an issue, since \@onExit is 29 | * a useless construct in such a case anyways. 30 | */ 31 | #define onExit \ 32 | ext_keywordify \ 33 | __strong ext_cleanupBlock_t metamacro_concat(ext_exitBlock_, __LINE__) __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^ 34 | 35 | /** 36 | * Creates \c __weak shadow variables for each of the variables provided as 37 | * arguments, which can later be made strong again with #strongify. 38 | * 39 | * This is typically used to weakly reference variables in a block, but then 40 | * ensure that the variables stay alive during the actual execution of the block 41 | * (if they were live upon entry). 42 | * 43 | * See #strongify for an example of usage. 44 | */ 45 | #define weakify(...) \ 46 | ext_keywordify \ 47 | metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__) 48 | 49 | /** 50 | * Like #weakify, but uses \c __unsafe_unretained instead, for targets or 51 | * classes that do not support weak references. 52 | */ 53 | #define unsafeify(...) \ 54 | ext_keywordify \ 55 | metamacro_foreach_cxt(ext_weakify_,, __unsafe_unretained, __VA_ARGS__) 56 | 57 | /** 58 | * Strongly references each of the variables provided as arguments, which must 59 | * have previously been passed to #weakify. 60 | * 61 | * The strong references created will shadow the original variable names, such 62 | * that the original names can be used without issue (and a significantly 63 | * reduced risk of retain cycles) in the current scope. 64 | * 65 | * @code 66 | 67 | id foo = [[NSObject alloc] init]; 68 | id bar = [[NSObject alloc] init]; 69 | 70 | @weakify(foo, bar); 71 | 72 | // this block will not keep 'foo' or 'bar' alive 73 | BOOL (^matchesFooOrBar)(id) = ^ BOOL (id obj){ 74 | // but now, upon entry, 'foo' and 'bar' will stay alive until the block has 75 | // finished executing 76 | @strongify(foo, bar); 77 | 78 | return [foo isEqual:obj] || [bar isEqual:obj]; 79 | }; 80 | 81 | * @endcode 82 | */ 83 | #define strongify(...) \ 84 | ext_keywordify \ 85 | _Pragma("clang diagnostic push") \ 86 | _Pragma("clang diagnostic ignored \"-Wshadow\"") \ 87 | metamacro_foreach(ext_strongify_,, __VA_ARGS__) \ 88 | _Pragma("clang diagnostic pop") 89 | 90 | /*** implementation details follow ***/ 91 | typedef void (^ext_cleanupBlock_t)(); 92 | 93 | #if defined(__cplusplus) 94 | extern "C" { 95 | #endif 96 | void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block); 97 | #if defined(__cplusplus) 98 | } 99 | #endif 100 | 101 | #define ext_weakify_(INDEX, CONTEXT, VAR) \ 102 | CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR); 103 | 104 | #define ext_strongify_(INDEX, VAR) \ 105 | __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_); 106 | 107 | // Details about the choice of backing keyword: 108 | // 109 | // The use of @try/@catch/@finally can cause the compiler to suppress 110 | // return-type warnings. 111 | // The use of @autoreleasepool {} is not optimized away by the compiler, 112 | // resulting in superfluous creation of autorelease pools. 113 | // 114 | // Since neither option is perfect, and with no other alternatives, the 115 | // compromise is to use @autorelease in DEBUG builds to maintain compiler 116 | // analysis, and to use @try/@catch otherwise to avoid insertion of unnecessary 117 | // autorelease pools. 118 | #if defined(DEBUG) && !defined(NDEBUG) 119 | #define ext_keywordify autoreleasepool {} 120 | #else 121 | #define ext_keywordify try {} @catch (...) {} 122 | #endif 123 | 124 | #define safeblock(block, ...) \ 125 | ext_keywordify \ 126 | block ? block(__VA_ARGS__) : nil 127 | -------------------------------------------------------------------------------- /BSStackView/Weakify/EXTScope.m: -------------------------------------------------------------------------------- 1 | // 2 | // EXTScope.m 3 | // extobjc 4 | // 5 | // Created by Justin Spahr-Summers on 2011-05-04. 6 | // Copyright (C) 2012 Justin Spahr-Summers. 7 | // Released under the MIT license. 8 | // 9 | 10 | #import "EXTScope.h" 11 | 12 | void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block) { 13 | (*block)(); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /BSStackView/Weakify/metamacros.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Macros for metaprogramming 3 | * ExtendedC 4 | * 5 | * Copyright (C) 2012 Justin Spahr-Summers 6 | * Released under the MIT license 7 | */ 8 | 9 | #ifndef EXTC_METAMACROS_H 10 | #define EXTC_METAMACROS_H 11 | 12 | 13 | /** 14 | * Executes one or more expressions (which may have a void type, such as a call 15 | * to a function that returns no value) and always returns true. 16 | */ 17 | #define metamacro_exprify(...) \ 18 | ((__VA_ARGS__), true) 19 | 20 | /** 21 | * Returns a string representation of VALUE after full macro expansion. 22 | */ 23 | #define metamacro_stringify(VALUE) \ 24 | metamacro_stringify_(VALUE) 25 | 26 | /** 27 | * Returns A and B concatenated after full macro expansion. 28 | */ 29 | #define metamacro_concat(A, B) \ 30 | metamacro_concat_(A, B) 31 | 32 | /** 33 | * Returns the Nth variadic argument (starting from zero). At least 34 | * N + 1 variadic arguments must be given. N must be between zero and twenty, 35 | * inclusive. 36 | */ 37 | #define metamacro_at(N, ...) \ 38 | metamacro_concat(metamacro_at, N)(__VA_ARGS__) 39 | 40 | /** 41 | * Returns the number of arguments (up to twenty) provided to the macro. At 42 | * least one argument must be provided. 43 | * 44 | * Inspired by P99: http://p99.gforge.inria.fr 45 | */ 46 | #define metamacro_argcount(...) \ 47 | metamacro_at(20, __VA_ARGS__, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1) 48 | 49 | /** 50 | * Identical to #metamacro_foreach_cxt, except that no CONTEXT argument is 51 | * given. Only the index and current argument will thus be passed to MACRO. 52 | */ 53 | #define metamacro_foreach(MACRO, SEP, ...) \ 54 | metamacro_foreach_cxt(metamacro_foreach_iter, SEP, MACRO, __VA_ARGS__) 55 | 56 | /** 57 | * For each consecutive variadic argument (up to twenty), MACRO is passed the 58 | * zero-based index of the current argument, CONTEXT, and then the argument 59 | * itself. The results of adjoining invocations of MACRO are then separated by 60 | * SEP. 61 | * 62 | * Inspired by P99: http://p99.gforge.inria.fr 63 | */ 64 | #define metamacro_foreach_cxt(MACRO, SEP, CONTEXT, ...) \ 65 | metamacro_concat(metamacro_foreach_cxt, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) 66 | 67 | /** 68 | * Identical to #metamacro_foreach_cxt. This can be used when the former would 69 | * fail due to recursive macro expansion. 70 | */ 71 | #define metamacro_foreach_cxt_recursive(MACRO, SEP, CONTEXT, ...) \ 72 | metamacro_concat(metamacro_foreach_cxt_recursive, metamacro_argcount(__VA_ARGS__))(MACRO, SEP, CONTEXT, __VA_ARGS__) 73 | 74 | /** 75 | * In consecutive order, appends each variadic argument (up to twenty) onto 76 | * BASE. The resulting concatenations are then separated by SEP. 77 | * 78 | * This is primarily useful to manipulate a list of macro invocations into instead 79 | * invoking a different, possibly related macro. 80 | */ 81 | #define metamacro_foreach_concat(BASE, SEP, ...) \ 82 | metamacro_foreach_cxt(metamacro_foreach_concat_iter, SEP, BASE, __VA_ARGS__) 83 | 84 | /** 85 | * Iterates COUNT times, each time invoking MACRO with the current index 86 | * (starting at zero) and CONTEXT. The results of adjoining invocations of MACRO 87 | * are then separated by SEP. 88 | * 89 | * COUNT must be an integer between zero and twenty, inclusive. 90 | */ 91 | #define metamacro_for_cxt(COUNT, MACRO, SEP, CONTEXT) \ 92 | metamacro_concat(metamacro_for_cxt, COUNT)(MACRO, SEP, CONTEXT) 93 | 94 | /** 95 | * Returns the first argument given. At least one argument must be provided. 96 | * 97 | * This is useful when implementing a variadic macro, where you may have only 98 | * one variadic argument, but no way to retrieve it (for example, because \c ... 99 | * always needs to match at least one argument). 100 | * 101 | * @code 102 | 103 | #define varmacro(...) \ 104 | metamacro_head(__VA_ARGS__) 105 | 106 | * @endcode 107 | */ 108 | #define metamacro_head(...) \ 109 | metamacro_head_(__VA_ARGS__, 0) 110 | 111 | /** 112 | * Returns every argument except the first. At least two arguments must be 113 | * provided. 114 | */ 115 | #define metamacro_tail(...) \ 116 | metamacro_tail_(__VA_ARGS__) 117 | 118 | /** 119 | * Returns the first N (up to twenty) variadic arguments as a new argument list. 120 | * At least N variadic arguments must be provided. 121 | */ 122 | #define metamacro_take(N, ...) \ 123 | metamacro_concat(metamacro_take, N)(__VA_ARGS__) 124 | 125 | /** 126 | * Removes the first N (up to twenty) variadic arguments from the given argument 127 | * list. At least N variadic arguments must be provided. 128 | */ 129 | #define metamacro_drop(N, ...) \ 130 | metamacro_concat(metamacro_drop, N)(__VA_ARGS__) 131 | 132 | /** 133 | * Decrements VAL, which must be a number between zero and twenty, inclusive. 134 | * 135 | * This is primarily useful when dealing with indexes and counts in 136 | * metaprogramming. 137 | */ 138 | #define metamacro_dec(VAL) \ 139 | metamacro_at(VAL, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19) 140 | 141 | /** 142 | * Increments VAL, which must be a number between zero and twenty, inclusive. 143 | * 144 | * This is primarily useful when dealing with indexes and counts in 145 | * metaprogramming. 146 | */ 147 | #define metamacro_inc(VAL) \ 148 | metamacro_at(VAL, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21) 149 | 150 | /** 151 | * If A is equal to B, the next argument list is expanded; otherwise, the 152 | * argument list after that is expanded. A and B must be numbers between zero 153 | * and twenty, inclusive. Additionally, B must be greater than or equal to A. 154 | * 155 | * @code 156 | 157 | // expands to true 158 | metamacro_if_eq(0, 0)(true)(false) 159 | 160 | // expands to false 161 | metamacro_if_eq(0, 1)(true)(false) 162 | 163 | * @endcode 164 | * 165 | * This is primarily useful when dealing with indexes and counts in 166 | * metaprogramming. 167 | */ 168 | #define metamacro_if_eq(A, B) \ 169 | metamacro_concat(metamacro_if_eq, A)(B) 170 | 171 | /** 172 | * Identical to #metamacro_if_eq. This can be used when the former would fail 173 | * due to recursive macro expansion. 174 | */ 175 | #define metamacro_if_eq_recursive(A, B) \ 176 | metamacro_concat(metamacro_if_eq_recursive, A)(B) 177 | 178 | /** 179 | * Returns 1 if N is an even number, or 0 otherwise. N must be between zero and 180 | * twenty, inclusive. 181 | * 182 | * For the purposes of this test, zero is considered even. 183 | */ 184 | #define metamacro_is_even(N) \ 185 | metamacro_at(N, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1) 186 | 187 | /** 188 | * Returns the logical NOT of B, which must be the number zero or one. 189 | */ 190 | #define metamacro_not(B) \ 191 | metamacro_at(B, 1, 0) 192 | 193 | // IMPLEMENTATION DETAILS FOLLOW! 194 | // Do not write code that depends on anything below this line. 195 | #define metamacro_stringify_(VALUE) # VALUE 196 | #define metamacro_concat_(A, B) A ## B 197 | #define metamacro_foreach_iter(INDEX, MACRO, ARG) MACRO(INDEX, ARG) 198 | #define metamacro_head_(FIRST, ...) FIRST 199 | #define metamacro_tail_(FIRST, ...) __VA_ARGS__ 200 | #define metamacro_consume_(...) 201 | #define metamacro_expand_(...) __VA_ARGS__ 202 | 203 | // implemented from scratch so that metamacro_concat() doesn't end up nesting 204 | #define metamacro_foreach_concat_iter(INDEX, BASE, ARG) metamacro_foreach_concat_iter_(BASE, ARG) 205 | #define metamacro_foreach_concat_iter_(BASE, ARG) BASE ## ARG 206 | 207 | // metamacro_at expansions 208 | #define metamacro_at0(...) metamacro_head(__VA_ARGS__) 209 | #define metamacro_at1(_0, ...) metamacro_head(__VA_ARGS__) 210 | #define metamacro_at2(_0, _1, ...) metamacro_head(__VA_ARGS__) 211 | #define metamacro_at3(_0, _1, _2, ...) metamacro_head(__VA_ARGS__) 212 | #define metamacro_at4(_0, _1, _2, _3, ...) metamacro_head(__VA_ARGS__) 213 | #define metamacro_at5(_0, _1, _2, _3, _4, ...) metamacro_head(__VA_ARGS__) 214 | #define metamacro_at6(_0, _1, _2, _3, _4, _5, ...) metamacro_head(__VA_ARGS__) 215 | #define metamacro_at7(_0, _1, _2, _3, _4, _5, _6, ...) metamacro_head(__VA_ARGS__) 216 | #define metamacro_at8(_0, _1, _2, _3, _4, _5, _6, _7, ...) metamacro_head(__VA_ARGS__) 217 | #define metamacro_at9(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) metamacro_head(__VA_ARGS__) 218 | #define metamacro_at10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) metamacro_head(__VA_ARGS__) 219 | #define metamacro_at11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) metamacro_head(__VA_ARGS__) 220 | #define metamacro_at12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) metamacro_head(__VA_ARGS__) 221 | #define metamacro_at13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) metamacro_head(__VA_ARGS__) 222 | #define metamacro_at14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) metamacro_head(__VA_ARGS__) 223 | #define metamacro_at15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) metamacro_head(__VA_ARGS__) 224 | #define metamacro_at16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) metamacro_head(__VA_ARGS__) 225 | #define metamacro_at17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) metamacro_head(__VA_ARGS__) 226 | #define metamacro_at18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) metamacro_head(__VA_ARGS__) 227 | #define metamacro_at19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) metamacro_head(__VA_ARGS__) 228 | #define metamacro_at20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) metamacro_head(__VA_ARGS__) 229 | 230 | // metamacro_foreach_cxt expansions 231 | #define metamacro_foreach_cxt0(MACRO, SEP, CONTEXT) 232 | #define metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) 233 | 234 | #define metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ 235 | metamacro_foreach_cxt1(MACRO, SEP, CONTEXT, _0) \ 236 | SEP \ 237 | MACRO(1, CONTEXT, _1) 238 | 239 | #define metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 240 | metamacro_foreach_cxt2(MACRO, SEP, CONTEXT, _0, _1) \ 241 | SEP \ 242 | MACRO(2, CONTEXT, _2) 243 | 244 | #define metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 245 | metamacro_foreach_cxt3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 246 | SEP \ 247 | MACRO(3, CONTEXT, _3) 248 | 249 | #define metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 250 | metamacro_foreach_cxt4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 251 | SEP \ 252 | MACRO(4, CONTEXT, _4) 253 | 254 | #define metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 255 | metamacro_foreach_cxt5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 256 | SEP \ 257 | MACRO(5, CONTEXT, _5) 258 | 259 | #define metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 260 | metamacro_foreach_cxt6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 261 | SEP \ 262 | MACRO(6, CONTEXT, _6) 263 | 264 | #define metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 265 | metamacro_foreach_cxt7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 266 | SEP \ 267 | MACRO(7, CONTEXT, _7) 268 | 269 | #define metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 270 | metamacro_foreach_cxt8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 271 | SEP \ 272 | MACRO(8, CONTEXT, _8) 273 | 274 | #define metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 275 | metamacro_foreach_cxt9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 276 | SEP \ 277 | MACRO(9, CONTEXT, _9) 278 | 279 | #define metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 280 | metamacro_foreach_cxt10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 281 | SEP \ 282 | MACRO(10, CONTEXT, _10) 283 | 284 | #define metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 285 | metamacro_foreach_cxt11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 286 | SEP \ 287 | MACRO(11, CONTEXT, _11) 288 | 289 | #define metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 290 | metamacro_foreach_cxt12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 291 | SEP \ 292 | MACRO(12, CONTEXT, _12) 293 | 294 | #define metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 295 | metamacro_foreach_cxt13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 296 | SEP \ 297 | MACRO(13, CONTEXT, _13) 298 | 299 | #define metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 300 | metamacro_foreach_cxt14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 301 | SEP \ 302 | MACRO(14, CONTEXT, _14) 303 | 304 | #define metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 305 | metamacro_foreach_cxt15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 306 | SEP \ 307 | MACRO(15, CONTEXT, _15) 308 | 309 | #define metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 310 | metamacro_foreach_cxt16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 311 | SEP \ 312 | MACRO(16, CONTEXT, _16) 313 | 314 | #define metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 315 | metamacro_foreach_cxt17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 316 | SEP \ 317 | MACRO(17, CONTEXT, _17) 318 | 319 | #define metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 320 | metamacro_foreach_cxt18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 321 | SEP \ 322 | MACRO(18, CONTEXT, _18) 323 | 324 | #define metamacro_foreach_cxt20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ 325 | metamacro_foreach_cxt19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 326 | SEP \ 327 | MACRO(19, CONTEXT, _19) 328 | 329 | // metamacro_foreach_cxt_recursive expansions 330 | #define metamacro_foreach_cxt_recursive0(MACRO, SEP, CONTEXT) 331 | #define metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) MACRO(0, CONTEXT, _0) 332 | 333 | #define metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ 334 | metamacro_foreach_cxt_recursive1(MACRO, SEP, CONTEXT, _0) \ 335 | SEP \ 336 | MACRO(1, CONTEXT, _1) 337 | 338 | #define metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 339 | metamacro_foreach_cxt_recursive2(MACRO, SEP, CONTEXT, _0, _1) \ 340 | SEP \ 341 | MACRO(2, CONTEXT, _2) 342 | 343 | #define metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 344 | metamacro_foreach_cxt_recursive3(MACRO, SEP, CONTEXT, _0, _1, _2) \ 345 | SEP \ 346 | MACRO(3, CONTEXT, _3) 347 | 348 | #define metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 349 | metamacro_foreach_cxt_recursive4(MACRO, SEP, CONTEXT, _0, _1, _2, _3) \ 350 | SEP \ 351 | MACRO(4, CONTEXT, _4) 352 | 353 | #define metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 354 | metamacro_foreach_cxt_recursive5(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4) \ 355 | SEP \ 356 | MACRO(5, CONTEXT, _5) 357 | 358 | #define metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 359 | metamacro_foreach_cxt_recursive6(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5) \ 360 | SEP \ 361 | MACRO(6, CONTEXT, _6) 362 | 363 | #define metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 364 | metamacro_foreach_cxt_recursive7(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6) \ 365 | SEP \ 366 | MACRO(7, CONTEXT, _7) 367 | 368 | #define metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 369 | metamacro_foreach_cxt_recursive8(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7) \ 370 | SEP \ 371 | MACRO(8, CONTEXT, _8) 372 | 373 | #define metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 374 | metamacro_foreach_cxt_recursive9(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8) \ 375 | SEP \ 376 | MACRO(9, CONTEXT, _9) 377 | 378 | #define metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 379 | metamacro_foreach_cxt_recursive10(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9) \ 380 | SEP \ 381 | MACRO(10, CONTEXT, _10) 382 | 383 | #define metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 384 | metamacro_foreach_cxt_recursive11(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ 385 | SEP \ 386 | MACRO(11, CONTEXT, _11) 387 | 388 | #define metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 389 | metamacro_foreach_cxt_recursive12(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ 390 | SEP \ 391 | MACRO(12, CONTEXT, _12) 392 | 393 | #define metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 394 | metamacro_foreach_cxt_recursive13(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ 395 | SEP \ 396 | MACRO(13, CONTEXT, _13) 397 | 398 | #define metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 399 | metamacro_foreach_cxt_recursive14(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ 400 | SEP \ 401 | MACRO(14, CONTEXT, _14) 402 | 403 | #define metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 404 | metamacro_foreach_cxt_recursive15(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ 405 | SEP \ 406 | MACRO(15, CONTEXT, _15) 407 | 408 | #define metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 409 | metamacro_foreach_cxt_recursive16(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ 410 | SEP \ 411 | MACRO(16, CONTEXT, _16) 412 | 413 | #define metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 414 | metamacro_foreach_cxt_recursive17(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ 415 | SEP \ 416 | MACRO(17, CONTEXT, _17) 417 | 418 | #define metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 419 | metamacro_foreach_cxt_recursive18(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17) \ 420 | SEP \ 421 | MACRO(18, CONTEXT, _18) 422 | 423 | #define metamacro_foreach_cxt_recursive20(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19) \ 424 | metamacro_foreach_cxt_recursive19(MACRO, SEP, CONTEXT, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18) \ 425 | SEP \ 426 | MACRO(19, CONTEXT, _19) 427 | 428 | // metamacro_for_cxt expansions 429 | #define metamacro_for_cxt0(MACRO, SEP, CONTEXT) 430 | #define metamacro_for_cxt1(MACRO, SEP, CONTEXT) MACRO(0, CONTEXT) 431 | 432 | #define metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ 433 | metamacro_for_cxt1(MACRO, SEP, CONTEXT) \ 434 | SEP \ 435 | MACRO(1, CONTEXT) 436 | 437 | #define metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ 438 | metamacro_for_cxt2(MACRO, SEP, CONTEXT) \ 439 | SEP \ 440 | MACRO(2, CONTEXT) 441 | 442 | #define metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ 443 | metamacro_for_cxt3(MACRO, SEP, CONTEXT) \ 444 | SEP \ 445 | MACRO(3, CONTEXT) 446 | 447 | #define metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ 448 | metamacro_for_cxt4(MACRO, SEP, CONTEXT) \ 449 | SEP \ 450 | MACRO(4, CONTEXT) 451 | 452 | #define metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ 453 | metamacro_for_cxt5(MACRO, SEP, CONTEXT) \ 454 | SEP \ 455 | MACRO(5, CONTEXT) 456 | 457 | #define metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ 458 | metamacro_for_cxt6(MACRO, SEP, CONTEXT) \ 459 | SEP \ 460 | MACRO(6, CONTEXT) 461 | 462 | #define metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ 463 | metamacro_for_cxt7(MACRO, SEP, CONTEXT) \ 464 | SEP \ 465 | MACRO(7, CONTEXT) 466 | 467 | #define metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ 468 | metamacro_for_cxt8(MACRO, SEP, CONTEXT) \ 469 | SEP \ 470 | MACRO(8, CONTEXT) 471 | 472 | #define metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ 473 | metamacro_for_cxt9(MACRO, SEP, CONTEXT) \ 474 | SEP \ 475 | MACRO(9, CONTEXT) 476 | 477 | #define metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ 478 | metamacro_for_cxt10(MACRO, SEP, CONTEXT) \ 479 | SEP \ 480 | MACRO(10, CONTEXT) 481 | 482 | #define metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ 483 | metamacro_for_cxt11(MACRO, SEP, CONTEXT) \ 484 | SEP \ 485 | MACRO(11, CONTEXT) 486 | 487 | #define metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ 488 | metamacro_for_cxt12(MACRO, SEP, CONTEXT) \ 489 | SEP \ 490 | MACRO(12, CONTEXT) 491 | 492 | #define metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ 493 | metamacro_for_cxt13(MACRO, SEP, CONTEXT) \ 494 | SEP \ 495 | MACRO(13, CONTEXT) 496 | 497 | #define metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ 498 | metamacro_for_cxt14(MACRO, SEP, CONTEXT) \ 499 | SEP \ 500 | MACRO(14, CONTEXT) 501 | 502 | #define metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ 503 | metamacro_for_cxt15(MACRO, SEP, CONTEXT) \ 504 | SEP \ 505 | MACRO(15, CONTEXT) 506 | 507 | #define metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ 508 | metamacro_for_cxt16(MACRO, SEP, CONTEXT) \ 509 | SEP \ 510 | MACRO(16, CONTEXT) 511 | 512 | #define metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ 513 | metamacro_for_cxt17(MACRO, SEP, CONTEXT) \ 514 | SEP \ 515 | MACRO(17, CONTEXT) 516 | 517 | #define metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ 518 | metamacro_for_cxt18(MACRO, SEP, CONTEXT) \ 519 | SEP \ 520 | MACRO(18, CONTEXT) 521 | 522 | #define metamacro_for_cxt20(MACRO, SEP, CONTEXT) \ 523 | metamacro_for_cxt19(MACRO, SEP, CONTEXT) \ 524 | SEP \ 525 | MACRO(19, CONTEXT) 526 | 527 | // metamacro_if_eq expansions 528 | #define metamacro_if_eq0(VALUE) \ 529 | metamacro_concat(metamacro_if_eq0_, VALUE) 530 | 531 | #define metamacro_if_eq0_0(...) __VA_ARGS__ metamacro_consume_ 532 | #define metamacro_if_eq0_1(...) metamacro_expand_ 533 | #define metamacro_if_eq0_2(...) metamacro_expand_ 534 | #define metamacro_if_eq0_3(...) metamacro_expand_ 535 | #define metamacro_if_eq0_4(...) metamacro_expand_ 536 | #define metamacro_if_eq0_5(...) metamacro_expand_ 537 | #define metamacro_if_eq0_6(...) metamacro_expand_ 538 | #define metamacro_if_eq0_7(...) metamacro_expand_ 539 | #define metamacro_if_eq0_8(...) metamacro_expand_ 540 | #define metamacro_if_eq0_9(...) metamacro_expand_ 541 | #define metamacro_if_eq0_10(...) metamacro_expand_ 542 | #define metamacro_if_eq0_11(...) metamacro_expand_ 543 | #define metamacro_if_eq0_12(...) metamacro_expand_ 544 | #define metamacro_if_eq0_13(...) metamacro_expand_ 545 | #define metamacro_if_eq0_14(...) metamacro_expand_ 546 | #define metamacro_if_eq0_15(...) metamacro_expand_ 547 | #define metamacro_if_eq0_16(...) metamacro_expand_ 548 | #define metamacro_if_eq0_17(...) metamacro_expand_ 549 | #define metamacro_if_eq0_18(...) metamacro_expand_ 550 | #define metamacro_if_eq0_19(...) metamacro_expand_ 551 | #define metamacro_if_eq0_20(...) metamacro_expand_ 552 | 553 | #define metamacro_if_eq1(VALUE) metamacro_if_eq0(metamacro_dec(VALUE)) 554 | #define metamacro_if_eq2(VALUE) metamacro_if_eq1(metamacro_dec(VALUE)) 555 | #define metamacro_if_eq3(VALUE) metamacro_if_eq2(metamacro_dec(VALUE)) 556 | #define metamacro_if_eq4(VALUE) metamacro_if_eq3(metamacro_dec(VALUE)) 557 | #define metamacro_if_eq5(VALUE) metamacro_if_eq4(metamacro_dec(VALUE)) 558 | #define metamacro_if_eq6(VALUE) metamacro_if_eq5(metamacro_dec(VALUE)) 559 | #define metamacro_if_eq7(VALUE) metamacro_if_eq6(metamacro_dec(VALUE)) 560 | #define metamacro_if_eq8(VALUE) metamacro_if_eq7(metamacro_dec(VALUE)) 561 | #define metamacro_if_eq9(VALUE) metamacro_if_eq8(metamacro_dec(VALUE)) 562 | #define metamacro_if_eq10(VALUE) metamacro_if_eq9(metamacro_dec(VALUE)) 563 | #define metamacro_if_eq11(VALUE) metamacro_if_eq10(metamacro_dec(VALUE)) 564 | #define metamacro_if_eq12(VALUE) metamacro_if_eq11(metamacro_dec(VALUE)) 565 | #define metamacro_if_eq13(VALUE) metamacro_if_eq12(metamacro_dec(VALUE)) 566 | #define metamacro_if_eq14(VALUE) metamacro_if_eq13(metamacro_dec(VALUE)) 567 | #define metamacro_if_eq15(VALUE) metamacro_if_eq14(metamacro_dec(VALUE)) 568 | #define metamacro_if_eq16(VALUE) metamacro_if_eq15(metamacro_dec(VALUE)) 569 | #define metamacro_if_eq17(VALUE) metamacro_if_eq16(metamacro_dec(VALUE)) 570 | #define metamacro_if_eq18(VALUE) metamacro_if_eq17(metamacro_dec(VALUE)) 571 | #define metamacro_if_eq19(VALUE) metamacro_if_eq18(metamacro_dec(VALUE)) 572 | #define metamacro_if_eq20(VALUE) metamacro_if_eq19(metamacro_dec(VALUE)) 573 | 574 | // metamacro_if_eq_recursive expansions 575 | #define metamacro_if_eq_recursive0(VALUE) \ 576 | metamacro_concat(metamacro_if_eq_recursive0_, VALUE) 577 | 578 | #define metamacro_if_eq_recursive0_0(...) __VA_ARGS__ metamacro_consume_ 579 | #define metamacro_if_eq_recursive0_1(...) metamacro_expand_ 580 | #define metamacro_if_eq_recursive0_2(...) metamacro_expand_ 581 | #define metamacro_if_eq_recursive0_3(...) metamacro_expand_ 582 | #define metamacro_if_eq_recursive0_4(...) metamacro_expand_ 583 | #define metamacro_if_eq_recursive0_5(...) metamacro_expand_ 584 | #define metamacro_if_eq_recursive0_6(...) metamacro_expand_ 585 | #define metamacro_if_eq_recursive0_7(...) metamacro_expand_ 586 | #define metamacro_if_eq_recursive0_8(...) metamacro_expand_ 587 | #define metamacro_if_eq_recursive0_9(...) metamacro_expand_ 588 | #define metamacro_if_eq_recursive0_10(...) metamacro_expand_ 589 | #define metamacro_if_eq_recursive0_11(...) metamacro_expand_ 590 | #define metamacro_if_eq_recursive0_12(...) metamacro_expand_ 591 | #define metamacro_if_eq_recursive0_13(...) metamacro_expand_ 592 | #define metamacro_if_eq_recursive0_14(...) metamacro_expand_ 593 | #define metamacro_if_eq_recursive0_15(...) metamacro_expand_ 594 | #define metamacro_if_eq_recursive0_16(...) metamacro_expand_ 595 | #define metamacro_if_eq_recursive0_17(...) metamacro_expand_ 596 | #define metamacro_if_eq_recursive0_18(...) metamacro_expand_ 597 | #define metamacro_if_eq_recursive0_19(...) metamacro_expand_ 598 | #define metamacro_if_eq_recursive0_20(...) metamacro_expand_ 599 | 600 | #define metamacro_if_eq_recursive1(VALUE) metamacro_if_eq_recursive0(metamacro_dec(VALUE)) 601 | #define metamacro_if_eq_recursive2(VALUE) metamacro_if_eq_recursive1(metamacro_dec(VALUE)) 602 | #define metamacro_if_eq_recursive3(VALUE) metamacro_if_eq_recursive2(metamacro_dec(VALUE)) 603 | #define metamacro_if_eq_recursive4(VALUE) metamacro_if_eq_recursive3(metamacro_dec(VALUE)) 604 | #define metamacro_if_eq_recursive5(VALUE) metamacro_if_eq_recursive4(metamacro_dec(VALUE)) 605 | #define metamacro_if_eq_recursive6(VALUE) metamacro_if_eq_recursive5(metamacro_dec(VALUE)) 606 | #define metamacro_if_eq_recursive7(VALUE) metamacro_if_eq_recursive6(metamacro_dec(VALUE)) 607 | #define metamacro_if_eq_recursive8(VALUE) metamacro_if_eq_recursive7(metamacro_dec(VALUE)) 608 | #define metamacro_if_eq_recursive9(VALUE) metamacro_if_eq_recursive8(metamacro_dec(VALUE)) 609 | #define metamacro_if_eq_recursive10(VALUE) metamacro_if_eq_recursive9(metamacro_dec(VALUE)) 610 | #define metamacro_if_eq_recursive11(VALUE) metamacro_if_eq_recursive10(metamacro_dec(VALUE)) 611 | #define metamacro_if_eq_recursive12(VALUE) metamacro_if_eq_recursive11(metamacro_dec(VALUE)) 612 | #define metamacro_if_eq_recursive13(VALUE) metamacro_if_eq_recursive12(metamacro_dec(VALUE)) 613 | #define metamacro_if_eq_recursive14(VALUE) metamacro_if_eq_recursive13(metamacro_dec(VALUE)) 614 | #define metamacro_if_eq_recursive15(VALUE) metamacro_if_eq_recursive14(metamacro_dec(VALUE)) 615 | #define metamacro_if_eq_recursive16(VALUE) metamacro_if_eq_recursive15(metamacro_dec(VALUE)) 616 | #define metamacro_if_eq_recursive17(VALUE) metamacro_if_eq_recursive16(metamacro_dec(VALUE)) 617 | #define metamacro_if_eq_recursive18(VALUE) metamacro_if_eq_recursive17(metamacro_dec(VALUE)) 618 | #define metamacro_if_eq_recursive19(VALUE) metamacro_if_eq_recursive18(metamacro_dec(VALUE)) 619 | #define metamacro_if_eq_recursive20(VALUE) metamacro_if_eq_recursive19(metamacro_dec(VALUE)) 620 | 621 | // metamacro_take expansions 622 | #define metamacro_take0(...) 623 | #define metamacro_take1(...) metamacro_head(__VA_ARGS__) 624 | #define metamacro_take2(...) metamacro_head(__VA_ARGS__), metamacro_take1(metamacro_tail(__VA_ARGS__)) 625 | #define metamacro_take3(...) metamacro_head(__VA_ARGS__), metamacro_take2(metamacro_tail(__VA_ARGS__)) 626 | #define metamacro_take4(...) metamacro_head(__VA_ARGS__), metamacro_take3(metamacro_tail(__VA_ARGS__)) 627 | #define metamacro_take5(...) metamacro_head(__VA_ARGS__), metamacro_take4(metamacro_tail(__VA_ARGS__)) 628 | #define metamacro_take6(...) metamacro_head(__VA_ARGS__), metamacro_take5(metamacro_tail(__VA_ARGS__)) 629 | #define metamacro_take7(...) metamacro_head(__VA_ARGS__), metamacro_take6(metamacro_tail(__VA_ARGS__)) 630 | #define metamacro_take8(...) metamacro_head(__VA_ARGS__), metamacro_take7(metamacro_tail(__VA_ARGS__)) 631 | #define metamacro_take9(...) metamacro_head(__VA_ARGS__), metamacro_take8(metamacro_tail(__VA_ARGS__)) 632 | #define metamacro_take10(...) metamacro_head(__VA_ARGS__), metamacro_take9(metamacro_tail(__VA_ARGS__)) 633 | #define metamacro_take11(...) metamacro_head(__VA_ARGS__), metamacro_take10(metamacro_tail(__VA_ARGS__)) 634 | #define metamacro_take12(...) metamacro_head(__VA_ARGS__), metamacro_take11(metamacro_tail(__VA_ARGS__)) 635 | #define metamacro_take13(...) metamacro_head(__VA_ARGS__), metamacro_take12(metamacro_tail(__VA_ARGS__)) 636 | #define metamacro_take14(...) metamacro_head(__VA_ARGS__), metamacro_take13(metamacro_tail(__VA_ARGS__)) 637 | #define metamacro_take15(...) metamacro_head(__VA_ARGS__), metamacro_take14(metamacro_tail(__VA_ARGS__)) 638 | #define metamacro_take16(...) metamacro_head(__VA_ARGS__), metamacro_take15(metamacro_tail(__VA_ARGS__)) 639 | #define metamacro_take17(...) metamacro_head(__VA_ARGS__), metamacro_take16(metamacro_tail(__VA_ARGS__)) 640 | #define metamacro_take18(...) metamacro_head(__VA_ARGS__), metamacro_take17(metamacro_tail(__VA_ARGS__)) 641 | #define metamacro_take19(...) metamacro_head(__VA_ARGS__), metamacro_take18(metamacro_tail(__VA_ARGS__)) 642 | #define metamacro_take20(...) metamacro_head(__VA_ARGS__), metamacro_take19(metamacro_tail(__VA_ARGS__)) 643 | 644 | // metamacro_drop expansions 645 | #define metamacro_drop0(...) __VA_ARGS__ 646 | #define metamacro_drop1(...) metamacro_tail(__VA_ARGS__) 647 | #define metamacro_drop2(...) metamacro_drop1(metamacro_tail(__VA_ARGS__)) 648 | #define metamacro_drop3(...) metamacro_drop2(metamacro_tail(__VA_ARGS__)) 649 | #define metamacro_drop4(...) metamacro_drop3(metamacro_tail(__VA_ARGS__)) 650 | #define metamacro_drop5(...) metamacro_drop4(metamacro_tail(__VA_ARGS__)) 651 | #define metamacro_drop6(...) metamacro_drop5(metamacro_tail(__VA_ARGS__)) 652 | #define metamacro_drop7(...) metamacro_drop6(metamacro_tail(__VA_ARGS__)) 653 | #define metamacro_drop8(...) metamacro_drop7(metamacro_tail(__VA_ARGS__)) 654 | #define metamacro_drop9(...) metamacro_drop8(metamacro_tail(__VA_ARGS__)) 655 | #define metamacro_drop10(...) metamacro_drop9(metamacro_tail(__VA_ARGS__)) 656 | #define metamacro_drop11(...) metamacro_drop10(metamacro_tail(__VA_ARGS__)) 657 | #define metamacro_drop12(...) metamacro_drop11(metamacro_tail(__VA_ARGS__)) 658 | #define metamacro_drop13(...) metamacro_drop12(metamacro_tail(__VA_ARGS__)) 659 | #define metamacro_drop14(...) metamacro_drop13(metamacro_tail(__VA_ARGS__)) 660 | #define metamacro_drop15(...) metamacro_drop14(metamacro_tail(__VA_ARGS__)) 661 | #define metamacro_drop16(...) metamacro_drop15(metamacro_tail(__VA_ARGS__)) 662 | #define metamacro_drop17(...) metamacro_drop16(metamacro_tail(__VA_ARGS__)) 663 | #define metamacro_drop18(...) metamacro_drop17(metamacro_tail(__VA_ARGS__)) 664 | #define metamacro_drop19(...) metamacro_drop18(metamacro_tail(__VA_ARGS__)) 665 | #define metamacro_drop20(...) metamacro_drop19(metamacro_tail(__VA_ARGS__)) 666 | 667 | #endif 668 | -------------------------------------------------------------------------------- /DemoResources/demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iBlacksus/BSStackView/54b17da2dbc2257b93f6b382afb7771ed41da8d4/DemoResources/demo.gif -------------------------------------------------------------------------------- /Example/BSStackView_Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 068F8E131F150F24008AAF6F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 068F8E121F150F24008AAF6F /* main.m */; }; 11 | 068F8E161F150F24008AAF6F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 068F8E151F150F24008AAF6F /* AppDelegate.m */; }; 12 | 068F8E191F150F24008AAF6F /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 068F8E181F150F24008AAF6F /* ViewController.m */; }; 13 | 068F8E1C1F150F24008AAF6F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 068F8E1A1F150F24008AAF6F /* Main.storyboard */; }; 14 | 068F8E1E1F150F24008AAF6F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 068F8E1D1F150F24008AAF6F /* Assets.xcassets */; }; 15 | 068F8E211F150F24008AAF6F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 068F8E1F1F150F24008AAF6F /* LaunchScreen.storyboard */; }; 16 | DA09EFDABC0CD8A4ABDEF0EC /* libPods-BSStackView_Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BBF247EB53D9090E4554ADEC /* libPods-BSStackView_Example.a */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXFileReference section */ 20 | 041CF46B12A059B4F8A56576 /* Pods-BSStackView_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BSStackView_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-BSStackView_Example/Pods-BSStackView_Example.release.xcconfig"; sourceTree = ""; }; 21 | 068F8E0E1F150F24008AAF6F /* BSStackView_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BSStackView_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 068F8E121F150F24008AAF6F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 23 | 068F8E141F150F24008AAF6F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 24 | 068F8E151F150F24008AAF6F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 25 | 068F8E171F150F24008AAF6F /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 26 | 068F8E181F150F24008AAF6F /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 27 | 068F8E1B1F150F24008AAF6F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 28 | 068F8E1D1F150F24008AAF6F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 29 | 068F8E201F150F24008AAF6F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 30 | 068F8E221F150F24008AAF6F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 4A568EB1E7D37BE420D137BF /* Pods-BSStackView_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BSStackView_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BSStackView_Example/Pods-BSStackView_Example.debug.xcconfig"; sourceTree = ""; }; 32 | BBF247EB53D9090E4554ADEC /* libPods-BSStackView_Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-BSStackView_Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | /* End PBXFileReference section */ 34 | 35 | /* Begin PBXFrameworksBuildPhase section */ 36 | 068F8E0B1F150F24008AAF6F /* Frameworks */ = { 37 | isa = PBXFrameworksBuildPhase; 38 | buildActionMask = 2147483647; 39 | files = ( 40 | DA09EFDABC0CD8A4ABDEF0EC /* libPods-BSStackView_Example.a in Frameworks */, 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 068F8E051F150F24008AAF6F = { 48 | isa = PBXGroup; 49 | children = ( 50 | 068F8E101F150F24008AAF6F /* BSStackView_Example */, 51 | 068F8E0F1F150F24008AAF6F /* Products */, 52 | B256207A1195B3B8C4D737F3 /* Pods */, 53 | 6CA64B1E70C220CB719E042A /* Frameworks */, 54 | ); 55 | sourceTree = ""; 56 | }; 57 | 068F8E0F1F150F24008AAF6F /* Products */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 068F8E0E1F150F24008AAF6F /* BSStackView_Example.app */, 61 | ); 62 | name = Products; 63 | sourceTree = ""; 64 | }; 65 | 068F8E101F150F24008AAF6F /* BSStackView_Example */ = { 66 | isa = PBXGroup; 67 | children = ( 68 | 068F8E141F150F24008AAF6F /* AppDelegate.h */, 69 | 068F8E151F150F24008AAF6F /* AppDelegate.m */, 70 | 068F8E171F150F24008AAF6F /* ViewController.h */, 71 | 068F8E181F150F24008AAF6F /* ViewController.m */, 72 | 068F8E1A1F150F24008AAF6F /* Main.storyboard */, 73 | 068F8E1D1F150F24008AAF6F /* Assets.xcassets */, 74 | 068F8E1F1F150F24008AAF6F /* LaunchScreen.storyboard */, 75 | 068F8E221F150F24008AAF6F /* Info.plist */, 76 | 068F8E111F150F24008AAF6F /* Supporting Files */, 77 | ); 78 | path = BSStackView_Example; 79 | sourceTree = ""; 80 | }; 81 | 068F8E111F150F24008AAF6F /* Supporting Files */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 068F8E121F150F24008AAF6F /* main.m */, 85 | ); 86 | name = "Supporting Files"; 87 | sourceTree = ""; 88 | }; 89 | 6CA64B1E70C220CB719E042A /* Frameworks */ = { 90 | isa = PBXGroup; 91 | children = ( 92 | BBF247EB53D9090E4554ADEC /* libPods-BSStackView_Example.a */, 93 | ); 94 | name = Frameworks; 95 | sourceTree = ""; 96 | }; 97 | B256207A1195B3B8C4D737F3 /* Pods */ = { 98 | isa = PBXGroup; 99 | children = ( 100 | 4A568EB1E7D37BE420D137BF /* Pods-BSStackView_Example.debug.xcconfig */, 101 | 041CF46B12A059B4F8A56576 /* Pods-BSStackView_Example.release.xcconfig */, 102 | ); 103 | name = Pods; 104 | sourceTree = ""; 105 | }; 106 | /* End PBXGroup section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | 068F8E0D1F150F24008AAF6F /* BSStackView_Example */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = 068F8E251F150F24008AAF6F /* Build configuration list for PBXNativeTarget "BSStackView_Example" */; 112 | buildPhases = ( 113 | 346720FECB248E4CC654A6FC /* [CP] Check Pods Manifest.lock */, 114 | 068F8E0A1F150F24008AAF6F /* Sources */, 115 | 068F8E0B1F150F24008AAF6F /* Frameworks */, 116 | 068F8E0C1F150F24008AAF6F /* Resources */, 117 | 941218059DA42F630567BE7D /* [CP] Embed Pods Frameworks */, 118 | 8B28F659DE18C2DC576F2CBB /* [CP] Copy Pods Resources */, 119 | ); 120 | buildRules = ( 121 | ); 122 | dependencies = ( 123 | ); 124 | name = BSStackView_Example; 125 | productName = BSStackView_Example; 126 | productReference = 068F8E0E1F150F24008AAF6F /* BSStackView_Example.app */; 127 | productType = "com.apple.product-type.application"; 128 | }; 129 | /* End PBXNativeTarget section */ 130 | 131 | /* Begin PBXProject section */ 132 | 068F8E061F150F24008AAF6F /* Project object */ = { 133 | isa = PBXProject; 134 | attributes = { 135 | LastUpgradeCheck = 0830; 136 | ORGANIZATIONNAME = iBlacksus; 137 | TargetAttributes = { 138 | 068F8E0D1F150F24008AAF6F = { 139 | CreatedOnToolsVersion = 8.3.3; 140 | DevelopmentTeam = LS7LKYHTNJ; 141 | ProvisioningStyle = Automatic; 142 | }; 143 | }; 144 | }; 145 | buildConfigurationList = 068F8E091F150F24008AAF6F /* Build configuration list for PBXProject "BSStackView_Example" */; 146 | compatibilityVersion = "Xcode 3.2"; 147 | developmentRegion = English; 148 | hasScannedForEncodings = 0; 149 | knownRegions = ( 150 | en, 151 | Base, 152 | ); 153 | mainGroup = 068F8E051F150F24008AAF6F; 154 | productRefGroup = 068F8E0F1F150F24008AAF6F /* Products */; 155 | projectDirPath = ""; 156 | projectRoot = ""; 157 | targets = ( 158 | 068F8E0D1F150F24008AAF6F /* BSStackView_Example */, 159 | ); 160 | }; 161 | /* End PBXProject section */ 162 | 163 | /* Begin PBXResourcesBuildPhase section */ 164 | 068F8E0C1F150F24008AAF6F /* Resources */ = { 165 | isa = PBXResourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | 068F8E211F150F24008AAF6F /* LaunchScreen.storyboard in Resources */, 169 | 068F8E1E1F150F24008AAF6F /* Assets.xcassets in Resources */, 170 | 068F8E1C1F150F24008AAF6F /* Main.storyboard in Resources */, 171 | ); 172 | runOnlyForDeploymentPostprocessing = 0; 173 | }; 174 | /* End PBXResourcesBuildPhase section */ 175 | 176 | /* Begin PBXShellScriptBuildPhase section */ 177 | 346720FECB248E4CC654A6FC /* [CP] Check Pods Manifest.lock */ = { 178 | isa = PBXShellScriptBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | ); 182 | inputPaths = ( 183 | ); 184 | name = "[CP] Check Pods Manifest.lock"; 185 | outputPaths = ( 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | shellPath = /bin/sh; 189 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 190 | showEnvVarsInLog = 0; 191 | }; 192 | 8B28F659DE18C2DC576F2CBB /* [CP] Copy Pods Resources */ = { 193 | isa = PBXShellScriptBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | ); 197 | inputPaths = ( 198 | ); 199 | name = "[CP] Copy Pods Resources"; 200 | outputPaths = ( 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | shellPath = /bin/sh; 204 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BSStackView_Example/Pods-BSStackView_Example-resources.sh\"\n"; 205 | showEnvVarsInLog = 0; 206 | }; 207 | 941218059DA42F630567BE7D /* [CP] Embed Pods Frameworks */ = { 208 | isa = PBXShellScriptBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | ); 212 | inputPaths = ( 213 | ); 214 | name = "[CP] Embed Pods Frameworks"; 215 | outputPaths = ( 216 | ); 217 | runOnlyForDeploymentPostprocessing = 0; 218 | shellPath = /bin/sh; 219 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BSStackView_Example/Pods-BSStackView_Example-frameworks.sh\"\n"; 220 | showEnvVarsInLog = 0; 221 | }; 222 | /* End PBXShellScriptBuildPhase section */ 223 | 224 | /* Begin PBXSourcesBuildPhase section */ 225 | 068F8E0A1F150F24008AAF6F /* Sources */ = { 226 | isa = PBXSourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | 068F8E191F150F24008AAF6F /* ViewController.m in Sources */, 230 | 068F8E161F150F24008AAF6F /* AppDelegate.m in Sources */, 231 | 068F8E131F150F24008AAF6F /* main.m in Sources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXSourcesBuildPhase section */ 236 | 237 | /* Begin PBXVariantGroup section */ 238 | 068F8E1A1F150F24008AAF6F /* Main.storyboard */ = { 239 | isa = PBXVariantGroup; 240 | children = ( 241 | 068F8E1B1F150F24008AAF6F /* Base */, 242 | ); 243 | name = Main.storyboard; 244 | sourceTree = ""; 245 | }; 246 | 068F8E1F1F150F24008AAF6F /* LaunchScreen.storyboard */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | 068F8E201F150F24008AAF6F /* Base */, 250 | ); 251 | name = LaunchScreen.storyboard; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXVariantGroup section */ 255 | 256 | /* Begin XCBuildConfiguration section */ 257 | 068F8E231F150F24008AAF6F /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_ANALYZER_NONNULL = YES; 262 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 263 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 264 | CLANG_CXX_LIBRARY = "libc++"; 265 | CLANG_ENABLE_MODULES = YES; 266 | CLANG_ENABLE_OBJC_ARC = YES; 267 | CLANG_WARN_BOOL_CONVERSION = YES; 268 | CLANG_WARN_CONSTANT_CONVERSION = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 271 | CLANG_WARN_EMPTY_BODY = YES; 272 | CLANG_WARN_ENUM_CONVERSION = YES; 273 | CLANG_WARN_INFINITE_RECURSION = YES; 274 | CLANG_WARN_INT_CONVERSION = YES; 275 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 276 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 277 | CLANG_WARN_UNREACHABLE_CODE = YES; 278 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 279 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 280 | COPY_PHASE_STRIP = NO; 281 | DEBUG_INFORMATION_FORMAT = dwarf; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | ENABLE_TESTABILITY = YES; 284 | GCC_C_LANGUAGE_STANDARD = gnu99; 285 | GCC_DYNAMIC_NO_PIC = NO; 286 | GCC_NO_COMMON_BLOCKS = YES; 287 | GCC_OPTIMIZATION_LEVEL = 0; 288 | GCC_PREPROCESSOR_DEFINITIONS = ( 289 | "DEBUG=1", 290 | "$(inherited)", 291 | ); 292 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 293 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 294 | GCC_WARN_UNDECLARED_SELECTOR = YES; 295 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 296 | GCC_WARN_UNUSED_FUNCTION = YES; 297 | GCC_WARN_UNUSED_VARIABLE = YES; 298 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 299 | MTL_ENABLE_DEBUG_INFO = YES; 300 | ONLY_ACTIVE_ARCH = YES; 301 | SDKROOT = iphoneos; 302 | }; 303 | name = Debug; 304 | }; 305 | 068F8E241F150F24008AAF6F /* Release */ = { 306 | isa = XCBuildConfiguration; 307 | buildSettings = { 308 | ALWAYS_SEARCH_USER_PATHS = NO; 309 | CLANG_ANALYZER_NONNULL = YES; 310 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 311 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 312 | CLANG_CXX_LIBRARY = "libc++"; 313 | CLANG_ENABLE_MODULES = YES; 314 | CLANG_ENABLE_OBJC_ARC = YES; 315 | CLANG_WARN_BOOL_CONVERSION = YES; 316 | CLANG_WARN_CONSTANT_CONVERSION = YES; 317 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 318 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 319 | CLANG_WARN_EMPTY_BODY = YES; 320 | CLANG_WARN_ENUM_CONVERSION = YES; 321 | CLANG_WARN_INFINITE_RECURSION = YES; 322 | CLANG_WARN_INT_CONVERSION = YES; 323 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 324 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 325 | CLANG_WARN_UNREACHABLE_CODE = YES; 326 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 327 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 328 | COPY_PHASE_STRIP = NO; 329 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 330 | ENABLE_NS_ASSERTIONS = NO; 331 | ENABLE_STRICT_OBJC_MSGSEND = YES; 332 | GCC_C_LANGUAGE_STANDARD = gnu99; 333 | GCC_NO_COMMON_BLOCKS = YES; 334 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 335 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 336 | GCC_WARN_UNDECLARED_SELECTOR = YES; 337 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 338 | GCC_WARN_UNUSED_FUNCTION = YES; 339 | GCC_WARN_UNUSED_VARIABLE = YES; 340 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 341 | MTL_ENABLE_DEBUG_INFO = NO; 342 | SDKROOT = iphoneos; 343 | VALIDATE_PRODUCT = YES; 344 | }; 345 | name = Release; 346 | }; 347 | 068F8E261F150F24008AAF6F /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | baseConfigurationReference = 4A568EB1E7D37BE420D137BF /* Pods-BSStackView_Example.debug.xcconfig */; 350 | buildSettings = { 351 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 352 | DEVELOPMENT_TEAM = LS7LKYHTNJ; 353 | INFOPLIST_FILE = BSStackView_Example/Info.plist; 354 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 356 | PRODUCT_BUNDLE_IDENTIFIER = "iBlacksus.BSStackView-Example"; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | }; 359 | name = Debug; 360 | }; 361 | 068F8E271F150F24008AAF6F /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | baseConfigurationReference = 041CF46B12A059B4F8A56576 /* Pods-BSStackView_Example.release.xcconfig */; 364 | buildSettings = { 365 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 366 | DEVELOPMENT_TEAM = LS7LKYHTNJ; 367 | INFOPLIST_FILE = BSStackView_Example/Info.plist; 368 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 369 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 370 | PRODUCT_BUNDLE_IDENTIFIER = "iBlacksus.BSStackView-Example"; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | }; 373 | name = Release; 374 | }; 375 | /* End XCBuildConfiguration section */ 376 | 377 | /* Begin XCConfigurationList section */ 378 | 068F8E091F150F24008AAF6F /* Build configuration list for PBXProject "BSStackView_Example" */ = { 379 | isa = XCConfigurationList; 380 | buildConfigurations = ( 381 | 068F8E231F150F24008AAF6F /* Debug */, 382 | 068F8E241F150F24008AAF6F /* Release */, 383 | ); 384 | defaultConfigurationIsVisible = 0; 385 | defaultConfigurationName = Release; 386 | }; 387 | 068F8E251F150F24008AAF6F /* Build configuration list for PBXNativeTarget "BSStackView_Example" */ = { 388 | isa = XCConfigurationList; 389 | buildConfigurations = ( 390 | 068F8E261F150F24008AAF6F /* Debug */, 391 | 068F8E271F150F24008AAF6F /* Release */, 392 | ); 393 | defaultConfigurationIsVisible = 0; 394 | defaultConfigurationName = Release; 395 | }; 396 | /* End XCConfigurationList section */ 397 | }; 398 | rootObject = 068F8E061F150F24008AAF6F /* Project object */; 399 | } 400 | -------------------------------------------------------------------------------- /Example/BSStackView_Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // BSStackView_Example 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // BSStackView_Example 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Example/BSStackView_Example/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // BSStackView_Example 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // BSStackView_Example 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "BSStackView.h" 11 | 12 | @interface ViewController () 13 | 14 | @property (strong, nonatomic) IBOutlet BSStackView *stackView; 15 | 16 | @end 17 | 18 | @implementation ViewController 19 | 20 | - (void)viewDidLoad { 21 | [super viewDidLoad]; 22 | 23 | NSMutableArray *views = [NSMutableArray array]; 24 | for (NSInteger i = 0; i < 5; i++) { 25 | [views addObject:[self viewWithLabel:i]]; 26 | } 27 | 28 | self.stackView.swipeDirections = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown; 29 | self.stackView.forwardDirections = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionUp; 30 | self.stackView.backwardDirections = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionDown; 31 | self.stackView.changeAlphaOnSendAnimation = YES; 32 | [self.stackView configureWithViews:views]; 33 | self.stackView.delegate = self; 34 | } 35 | 36 | - (UIView *)viewWithLabel:(NSInteger)index { 37 | UIView *view = [[UIView alloc] initWithFrame:self.view.bounds]; 38 | view.backgroundColor = [UIColor whiteColor]; 39 | 40 | UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0., 0., 100., 100.)]; 41 | label.text = [NSString stringWithFormat:@"%ld", index]; 42 | label.textColor = [UIColor blackColor]; 43 | label.font = [UIFont systemFontOfSize:25.]; 44 | label.textAlignment = NSTextAlignmentCenter; 45 | [view addSubview:label]; 46 | 47 | return view; 48 | } 49 | 50 | - (NSString *)translateDirection:(BSStackViewItemDirection)direction { 51 | switch (direction) { 52 | case BSStackViewItemDirectionFront: 53 | return @"front"; 54 | 55 | case BSStackViewItemDirectionBack: 56 | return @"back"; 57 | } 58 | } 59 | 60 | #pragma mark - BSStackViewProtocol - 61 | 62 | - (void)stackView:(BSStackView *)stackView willSendItem:(UIView *)item direction:(BSStackViewItemDirection)direction { 63 | NSLog(@"stackView willSendItem %ld direction %@", item.tag, [self translateDirection:direction]); 64 | } 65 | 66 | - (void)stackView:(BSStackView *)stackView didSendItem:(UIView *)item direction:(BSStackViewItemDirection)direction { 67 | NSLog(@"stackView didSendItem %ld direction %@", item.tag, [self translateDirection:direction]); 68 | } 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Example/BSStackView_Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // BSStackView_Example 4 | // 5 | // Created by Oleg Musinov on 7/11/17. 6 | // Copyright © 2017 iBlacksus. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Example/podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | inhibit_all_warnings! 4 | 5 | source 'https://github.com/CocoaPods/Specs.git' 6 | 7 | target :'BSStackView_Example' do 8 | pod 'BSStackView' 9 | end -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 iBlacksus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BSStackView 2 | 3 | ![Image](DemoResources/demo.gif) 4 | 5 | BSStackView is available through [CocoaPods](http://cocoapods.org). To install 6 | it, simply add the following line to your Podfile: 7 | 8 | ```ruby 9 | pod "BSStackView" 10 | ``` 11 | or install manually by downloading the files from GitHub and then use 12 | ```ObjC 13 | #import "BSStackView.h" 14 | ``` 15 | 16 | ## Usage 17 | 18 | ## To run the example project, clone the repo, and run `pod install` from the Example directory first. 19 | 20 | Add the below reference to the @interface method in the header file(.h) 21 | ```ObjC 22 | @property (nonatomic, strong) IBOutlet BSStackView *stackView; 23 | ``` 24 | 25 | Initialize the BSStackView in the Implementation File (.m) 26 | ```ObjC 27 | self.stackView.swipeDirections = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionDown; 28 | self.stackView.forwardDirections = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionUp; 29 | self.stackView.backwardDirections = UISwipeGestureRecognizerDirectionLeft | UISwipeGestureRecognizerDirectionDown; 30 | self.stackView.changeAlphaOnSendAnimation = YES; 31 | [self.stackView configureWithViews:views]; 32 | self.stackView.delegate = self; 33 | ``` 34 | 35 | Customize constraints 36 | ```ObjC 37 | self.stackView.contraintsConfigurator.top = 20.; 38 | self.stackView.contraintsConfigurator.bottom = 50.; 39 | self.stackView.contraintsConfigurator.leading = 10.; 40 | self.stackView.contraintsConfigurator.trailing = 10.; 41 | [self.stackView configureWithViews:views]; 42 | ``` 43 | 44 | ## Requirements 45 | * iOS 8.0 or higher 46 | * ARC 47 | 48 | ## Author 49 | 50 | iBlacksus, iblacksus@gmail.com 51 | 52 | ## License 53 | 54 | BSStackView is available under the MIT license. See the LICENSE file for more info. 55 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect --------------------------------------------------------------------------------