diff --git a/LayoutKit.xcodeproj/project.pbxproj b/LayoutKit.xcodeproj/project.pbxproj index 3bb0fde8..d3e9643a 100644 --- a/LayoutKit.xcodeproj/project.pbxproj +++ b/LayoutKit.xcodeproj/project.pbxproj @@ -223,6 +223,22 @@ 7E233E63202E5F870012DD1E /* LOKButtonLayoutType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E233E62202E5F870012DD1E /* LOKButtonLayoutType.swift */; }; 7E233E65203129680012DD1E /* LOKOverlayLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E233E64203129680012DD1E /* LOKOverlayLayout.swift */; }; 7E233E67203130110012DD1E /* LOKTextViewLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E233E66203130110012DD1E /* LOKTextViewLayout.swift */; }; + 7E7370EA2051A494007C19FF /* LOKInsetLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370E82051A494007C19FF /* LOKInsetLayoutBuilder.h */; }; + 7E7370EB2051A494007C19FF /* LOKInsetLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370E92051A494007C19FF /* LOKInsetLayoutBuilder.m */; }; + 7E7370EE2051E08F007C19FF /* LOKLabelLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370EC2051E08F007C19FF /* LOKLabelLayoutBuilder.h */; }; + 7E7370EF2051E08F007C19FF /* LOKLabelLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370ED2051E08F007C19FF /* LOKLabelLayoutBuilder.m */; }; + 7E7370F22051E3E6007C19FF /* LOKBaseLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370F02051E3E6007C19FF /* LOKBaseLayoutBuilder.h */; }; + 7E7370F32051E3E6007C19FF /* LOKBaseLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370F12051E3E6007C19FF /* LOKBaseLayoutBuilder.m */; }; + 7E7370F62051ED84007C19FF /* LOKButtonLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370F42051ED84007C19FF /* LOKButtonLayoutBuilder.h */; }; + 7E7370F72051ED84007C19FF /* LOKButtonLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370F52051ED84007C19FF /* LOKButtonLayoutBuilder.m */; }; + 7E7370FA2051F415007C19FF /* LOKOverlayLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370F82051F415007C19FF /* LOKOverlayLayoutBuilder.h */; }; + 7E7370FB2051F415007C19FF /* LOKOverlayLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370F92051F415007C19FF /* LOKOverlayLayoutBuilder.m */; }; + 7E7370FE2051F86D007C19FF /* LOKSizeLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E7370FC2051F86D007C19FF /* LOKSizeLayoutBuilder.h */; }; + 7E7370FF2051F86D007C19FF /* LOKSizeLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E7370FD2051F86D007C19FF /* LOKSizeLayoutBuilder.m */; }; + 7E73710220520CA8007C19FF /* LOKStackLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E73710020520CA8007C19FF /* LOKStackLayoutBuilder.h */; }; + 7E73710320520CA8007C19FF /* LOKStackLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E73710120520CA8007C19FF /* LOKStackLayoutBuilder.m */; }; + 7E73710620520F5F007C19FF /* LOKTextViewLayoutBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E73710420520F5F007C19FF /* LOKTextViewLayoutBuilder.h */; }; + 7E73710720520F5F007C19FF /* LOKTextViewLayoutBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E73710520520F5F007C19FF /* LOKTextViewLayoutBuilder.m */; }; 7E7B83B6201E550F0001E279 /* LOKLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7B83B5201E550F0001E279 /* LOKLayout.swift */; }; 7E7B83B8201E554A0001E279 /* WrappedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7B83B7201E554A0001E279 /* WrappedLayout.swift */; }; 7E7B83BA201E55690001E279 /* ReverseWrappedLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E7B83B9201E55690001E279 /* ReverseWrappedLayout.swift */; }; @@ -432,6 +448,22 @@ 7E233E62202E5F870012DD1E /* LOKButtonLayoutType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOKButtonLayoutType.swift; sourceTree = ""; }; 7E233E64203129680012DD1E /* LOKOverlayLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOKOverlayLayout.swift; sourceTree = ""; }; 7E233E66203130110012DD1E /* LOKTextViewLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOKTextViewLayout.swift; sourceTree = ""; }; + 7E7370E82051A494007C19FF /* LOKInsetLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKInsetLayoutBuilder.h; sourceTree = ""; }; + 7E7370E92051A494007C19FF /* LOKInsetLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKInsetLayoutBuilder.m; sourceTree = ""; }; + 7E7370EC2051E08F007C19FF /* LOKLabelLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKLabelLayoutBuilder.h; sourceTree = ""; }; + 7E7370ED2051E08F007C19FF /* LOKLabelLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKLabelLayoutBuilder.m; sourceTree = ""; }; + 7E7370F02051E3E6007C19FF /* LOKBaseLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKBaseLayoutBuilder.h; sourceTree = ""; }; + 7E7370F12051E3E6007C19FF /* LOKBaseLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKBaseLayoutBuilder.m; sourceTree = ""; }; + 7E7370F42051ED84007C19FF /* LOKButtonLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKButtonLayoutBuilder.h; sourceTree = ""; }; + 7E7370F52051ED84007C19FF /* LOKButtonLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKButtonLayoutBuilder.m; sourceTree = ""; }; + 7E7370F82051F415007C19FF /* LOKOverlayLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKOverlayLayoutBuilder.h; sourceTree = ""; }; + 7E7370F92051F415007C19FF /* LOKOverlayLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKOverlayLayoutBuilder.m; sourceTree = ""; }; + 7E7370FC2051F86D007C19FF /* LOKSizeLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKSizeLayoutBuilder.h; sourceTree = ""; }; + 7E7370FD2051F86D007C19FF /* LOKSizeLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKSizeLayoutBuilder.m; sourceTree = ""; }; + 7E73710020520CA8007C19FF /* LOKStackLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKStackLayoutBuilder.h; sourceTree = ""; }; + 7E73710120520CA8007C19FF /* LOKStackLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKStackLayoutBuilder.m; sourceTree = ""; }; + 7E73710420520F5F007C19FF /* LOKTextViewLayoutBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LOKTextViewLayoutBuilder.h; sourceTree = ""; }; + 7E73710520520F5F007C19FF /* LOKTextViewLayoutBuilder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LOKTextViewLayoutBuilder.m; sourceTree = ""; }; 7E7B83B5201E550F0001E279 /* LOKLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LOKLayout.swift; sourceTree = ""; }; 7E7B83B7201E554A0001E279 /* WrappedLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedLayout.swift; sourceTree = ""; }; 7E7B83B9201E55690001E279 /* ReverseWrappedLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReverseWrappedLayout.swift; sourceTree = ""; }; @@ -752,9 +784,33 @@ path = Internal; sourceTree = ""; }; + 7E7370E72051A3FA007C19FF /* Builders */ = { + isa = PBXGroup; + children = ( + 7E7370F02051E3E6007C19FF /* LOKBaseLayoutBuilder.h */, + 7E7370F12051E3E6007C19FF /* LOKBaseLayoutBuilder.m */, + 7E7370F42051ED84007C19FF /* LOKButtonLayoutBuilder.h */, + 7E7370F52051ED84007C19FF /* LOKButtonLayoutBuilder.m */, + 7E7370E82051A494007C19FF /* LOKInsetLayoutBuilder.h */, + 7E7370E92051A494007C19FF /* LOKInsetLayoutBuilder.m */, + 7E7370EC2051E08F007C19FF /* LOKLabelLayoutBuilder.h */, + 7E7370ED2051E08F007C19FF /* LOKLabelLayoutBuilder.m */, + 7E7370F82051F415007C19FF /* LOKOverlayLayoutBuilder.h */, + 7E7370F92051F415007C19FF /* LOKOverlayLayoutBuilder.m */, + 7E7370FC2051F86D007C19FF /* LOKSizeLayoutBuilder.h */, + 7E7370FD2051F86D007C19FF /* LOKSizeLayoutBuilder.m */, + 7E73710020520CA8007C19FF /* LOKStackLayoutBuilder.h */, + 7E73710120520CA8007C19FF /* LOKStackLayoutBuilder.m */, + 7E73710420520F5F007C19FF /* LOKTextViewLayoutBuilder.h */, + 7E73710520520F5F007C19FF /* LOKTextViewLayoutBuilder.m */, + ); + path = Builders; + sourceTree = ""; + }; 7E7B83B4201E54F30001E279 /* ObjCSupport */ = { isa = PBXGroup; children = ( + 7E7370E72051A3FA007C19FF /* Builders */, 7E3107A82033B820009BA47A /* Internal */, 7E7B83C3201E5EB20001E279 /* LOKAlignment.swift */, 7E7B83C7201E8DDF0001E279 /* LOKBaseLayout.swift */, @@ -810,6 +866,14 @@ buildActionMask = 2147483647; files = ( 0BCB75701D8720110065E02A /* LayoutKit.h in Headers */, + 7E7370F62051ED84007C19FF /* LOKButtonLayoutBuilder.h in Headers */, + 7E7370FA2051F415007C19FF /* LOKOverlayLayoutBuilder.h in Headers */, + 7E7370FE2051F86D007C19FF /* LOKSizeLayoutBuilder.h in Headers */, + 7E7370EA2051A494007C19FF /* LOKInsetLayoutBuilder.h in Headers */, + 7E7370F22051E3E6007C19FF /* LOKBaseLayoutBuilder.h in Headers */, + 7E73710220520CA8007C19FF /* LOKStackLayoutBuilder.h in Headers */, + 7E7370EE2051E08F007C19FF /* LOKLabelLayoutBuilder.h in Headers */, + 7E73710620520F5F007C19FF /* LOKTextViewLayoutBuilder.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1191,6 +1255,7 @@ files = ( 0BCB76051D8724800065E02A /* StackLayout.swift in Sources */, 7E233E58202CEAB80012DD1E /* LOKLayoutArrangementSection.swift in Sources */, + 7E7370F72051ED84007C19FF /* LOKButtonLayoutBuilder.m in Sources */, 0BCB760D1D8724800065E02A /* LayoutAdapterTableView.swift in Sources */, 0BCB76071D8724800065E02A /* AxisPoint.swift in Sources */, 7E7B83BA201E55690001E279 /* ReverseWrappedLayout.swift in Sources */, @@ -1211,6 +1276,7 @@ 7E7B83B6201E550F0001E279 /* LOKLayout.swift in Sources */, 75D94A361EA01B6A00A5FD01 /* OverlayLayout.swift in Sources */, 0BCB75FD1D8724800065E02A /* CGSizeExtension.swift in Sources */, + 7E7370FB2051F415007C19FF /* LOKOverlayLayoutBuilder.m in Sources */, 7E7B83E120279CD10001E279 /* LOKReloadableViewLayoutAdapter.swift in Sources */, 0BCB760B1D8724800065E02A /* BatchUpdates.swift in Sources */, 7E7B83DF202101340001E279 /* LOKStackLayout.swift in Sources */, @@ -1218,6 +1284,7 @@ 7E7B83C2201E57230001E279 /* LOKInsetLayout.swift in Sources */, 0BCB75FA1D8724800065E02A /* ConfigurableLayout.swift in Sources */, 7E233E56202CEA8A0012DD1E /* LOKLayoutSection.swift in Sources */, + 7E7370EF2051E08F007C19FF /* LOKLabelLayoutBuilder.m in Sources */, 0BCB76111D8724800065E02A /* ReloadableViewLayoutAdapter.swift in Sources */, 0BCB75F91D8724800065E02A /* Axis.swift in Sources */, 0BCB760A1D8724800065E02A /* ViewRecycler.swift in Sources */, @@ -1228,24 +1295,29 @@ 0BCB75FF1D8724800065E02A /* LayoutArrangement.swift in Sources */, 0BCB760F1D8724800065E02A /* ReloadableViewLayoutAdapter+UICollectionView.swift in Sources */, 0BCB75F61D8724800065E02A /* Alignment.swift in Sources */, + 7E73710720520F5F007C19FF /* LOKTextViewLayoutBuilder.m in Sources */, 7E7B83C6201E60BA0001E279 /* LOKLabelLayout.swift in Sources */, + 7E73710320520CA8007C19FF /* LOKStackLayoutBuilder.m in Sources */, 7E233E65203129680012DD1E /* LOKOverlayLayout.swift in Sources */, 0B193BB91D887BCF00FCA22D /* IndexSetExtension.swift in Sources */, 0BCB75FC1D8724800065E02A /* CFAbsoluteTimeExtension.swift in Sources */, 0B765F2C1DC0514F000BF1FD /* CGFloatExtension.swift in Sources */, 7E233E67203130110012DD1E /* LOKTextViewLayout.swift in Sources */, + 7E7370EB2051A494007C19FF /* LOKInsetLayoutBuilder.m in Sources */, 0BCB76041D8724800065E02A /* SizeLayout.swift in Sources */, 7E233E61202E2CC00012DD1E /* LOKButtonLayout.swift in Sources */, 7E7B83C0201E56590001E279 /* LOKLayoutMeasurement.swift in Sources */, 0BCB76031D8724800065E02A /* LabelLayout.swift in Sources */, 0BCB76101D8724800065E02A /* ReloadableViewLayoutAdapter+UITableView.swift in Sources */, 7E7B83DD2020F7830001E279 /* LOKSizeLayout.swift in Sources */, + 7E7370FF2051F86D007C19FF /* LOKSizeLayoutBuilder.m in Sources */, 7E7B83BC201E55B30001E279 /* LOKFlexibility.swift in Sources */, 7E233E63202E5F870012DD1E /* LOKButtonLayoutType.swift in Sources */, 0BCB75FB1D8724800065E02A /* Flexibility.swift in Sources */, 0BCB76121D8724800065E02A /* ReloadableViewUpdateManager.swift in Sources */, 44F968151E425F5D00392763 /* TextViewLayout.swift in Sources */, 0BD42BDC1DB5EAAD00E04AA3 /* Text.swift in Sources */, + 7E7370F32051E3E6007C19FF /* LOKBaseLayoutBuilder.m in Sources */, 0BCB76131D8724800065E02A /* StackView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/LayoutKitObjCSampleApp/ViewController.m b/LayoutKitObjCSampleApp/ViewController.m index bb320b15..5907c738 100644 --- a/LayoutKitObjCSampleApp/ViewController.m +++ b/LayoutKitObjCSampleApp/ViewController.m @@ -8,6 +8,10 @@ #import "ViewController.h" #import "RotationLayout.h" +#import "LOKLabelLayoutBuilder.h" +#import "LOKInsetLayoutBuilder.h" +#import "LOKSizeLayoutBuilder.h" +#import "LOKStackLayoutBuilder.h" @import Foundation; @import UIKit; @@ -64,16 +68,9 @@ - (void)viewDidLoad { collectionView.delegate = self.adapter; collectionView.dataSource = self.adapter; - LOKSizeLayout *cellLayout = [[LOKSizeLayout alloc] initWithMinWidth:self.view.bounds.size.width - maxWidth:self.view.bounds.size.width - minHeight:0 - maxHeight:INFINITY - alignment:nil - flexibility:nil - viewReuseId:nil - viewClass:nil - sublayout:self.helloWorldLayout - configure:nil]; + LOKSizeLayoutBuilder *cellLayoutBuilder = [LOKSizeLayoutBuilder withSublayout:self.helloWorldLayout]; + cellLayoutBuilder.width = self.view.bounds.size.width; + LOKSizeLayout *cellLayout = [cellLayoutBuilder build]; NSArray *items = @[ cellLayout, cellLayout, cellLayout, cellLayout, @@ -109,44 +106,26 @@ - (void)viewDidLayoutSubviews { } + (id)makeHelloLayout { - LOKLabelLayout *labelLayoutA = [[LOKLabelLayout alloc] initWithString:@"Hello" - font:[UIFont systemFontOfSize:UIFont.systemFontSize] - lineHeight:0 - numberOfLines:0 - alignment:LOKAlignment.fill - flexibility:LOKFlexibility.flexible - viewReuseId:nil - viewClass:MyLabelView.class - configure:^(UILabel *label) { - label.backgroundColor = UIColor.whiteColor; - }]; - LOKLabelLayout *labelLayoutB = [[LOKLabelLayout alloc] initWithString:@"world!" - font:[UIFont systemFontOfSize:UIFont.systemFontSize] - lineHeight:0 - numberOfLines:0 - alignment:LOKAlignment.fill - flexibility:LOKFlexibility.flexible - viewReuseId:nil - viewClass:MyLabelView.class - configure:^(UILabel *label) { - label.backgroundColor = UIColor.whiteColor; - }]; - LOKStackLayout *stackLayout = [[LOKStackLayout alloc] initWithAxis:LOKAxisHorizontal - spacing:10 - distribution:LOKStackLayoutDistributionDefault - alignment:nil - flexibility:nil - viewClass:nil - viewReuseId:nil - sublayouts:@[labelLayoutA, labelLayoutB] - configure:nil]; - LOKInsetLayout *insetLayout = [[LOKInsetLayout alloc] initWithInsets:UIEdgeInsetsMake(20, 20, 20, 20) - alignment:LOKAlignment.fill - viewReuseId:nil - viewClass:LabelBackgroundView.class - sublayout:stackLayout - configure:^(UIView *view) { }]; - return [[RotationLayout alloc] initWithSublayout:insetLayout + LOKLabelLayoutBuilder *labelLayoutBuilderA = [LOKLabelLayoutBuilder withString:@"Hello"]; + labelLayoutBuilderA.viewClass = MyLabelView.class; + labelLayoutBuilderA.configure = ^(UIView * _Nonnull label) { + label.backgroundColor = UIColor.whiteColor; + }; + LOKLabelLayout *labelLayoutA = [labelLayoutBuilderA build]; + LOKLabelLayoutBuilder *labelLayoutBuilderB = [LOKLabelLayoutBuilder withString:@"world!"]; + labelLayoutBuilderB.viewClass = MyLabelView.class; + labelLayoutBuilderB.configure = ^(UIView * _Nonnull label) { + label.backgroundColor = UIColor.whiteColor; + }; + LOKLabelLayout *labelLayoutB = [labelLayoutBuilderB build]; + LOKStackLayoutBuilder *stackLayoutBuilder = [LOKStackLayoutBuilder withSublayouts:@[labelLayoutA, labelLayoutB]]; + stackLayoutBuilder.axis = LOKAxisHorizontal; + stackLayoutBuilder.spacing = 10; + LOKInsetLayoutBuilder *insetLayoutBuilder = [LOKInsetLayoutBuilder withInsets:UIEdgeInsetsMake(20, 20, 20, 20) around:[stackLayoutBuilder build]]; + insetLayoutBuilder.alignment = LOKAlignment.fill; + insetLayoutBuilder.viewClass = LabelBackgroundView.class; + insetLayoutBuilder.configure = ^(UIView * _Nonnull view) { }; + return [[RotationLayout alloc] initWithSublayout:[insetLayoutBuilder build] alignment:LOKAlignment.center viewReuseId:nil]; } diff --git a/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.h new file mode 100644 index 00000000..37543918 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.h @@ -0,0 +1,22 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import +#import + +@interface LOKBaseLayoutBuilder : NSObject + +@property (nonatomic, nullable) LOKAlignment *alignment; +@property (nonatomic, nullable) LOKFlexibility *flexibility; +@property (nonatomic, nullable) NSString *viewReuseId; +@property (nonatomic, nullable) Class viewClass; +@property (nonatomic, nullable) void (^ configure)(UIView * _Nonnull); + +- (nonnull id)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.m new file mode 100644 index 00000000..cfd2fb84 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKBaseLayoutBuilder.m @@ -0,0 +1,13 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@implementation LOKBaseLayoutBuilder + +@end diff --git a/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.h new file mode 100644 index 00000000..9643174d --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.h @@ -0,0 +1,24 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKButtonLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withTitle:(nullable NSString *)title; + +@property (nonatomic) LOKButtonLayoutType type; +@property (nonatomic, nullable) NSString *title; +@property (nonatomic, nullable) UIFont *font; +@property (nonatomic, nullable) UIImage *image; +@property (nonatomic) CGSize imageSize; +@property (nonatomic, nullable) NSValue *contentEdgeInsets; + +- (nonnull LOKButtonLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.m new file mode 100644 index 00000000..7f84f01e --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKButtonLayoutBuilder.m @@ -0,0 +1,33 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKButtonLayoutBuilder.h" + +@implementation LOKButtonLayoutBuilder + ++ (instancetype)withTitle:(NSString *)title { + LOKButtonLayoutBuilder *builder = [[self alloc] init]; + builder.title = title; + return builder; +} + +- (LOKButtonLayout *)build { + return [[LOKButtonLayout alloc] initWithType:self.type + title:self.title + image:self.image + imageSize:self.imageSize + font:self.font + contentEdgeInsets:self.contentEdgeInsets + alignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + config:self.configure]; +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.h new file mode 100644 index 00000000..0928bac5 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.h @@ -0,0 +1,20 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKInsetLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withInsets:(UIEdgeInsets)insets around:(nonnull id)sublayout; + +@property (nonatomic) UIEdgeInsets insets; +@property (nonatomic, nonnull) id sublayout; + +- (nonnull LOKInsetLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.m new file mode 100644 index 00000000..44e36cbe --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKInsetLayoutBuilder.m @@ -0,0 +1,31 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKInsetLayoutBuilder.h" + +@implementation LOKInsetLayoutBuilder + ++ (nonnull instancetype)withInsets:(UIEdgeInsets)insets around:(nonnull id)sublayout { + LOKInsetLayoutBuilder *builder = [[self alloc] init]; + if (builder) { + builder.insets = insets; + builder.sublayout = sublayout; + } + return builder; +} + +- (nonnull LOKInsetLayout *)build { + return [[LOKInsetLayout alloc] initWithInsets:self.insets + alignment:self.alignment + viewReuseId:self.viewReuseId + viewClass:self.viewClass + sublayout:self.sublayout + configure:self.configure]; +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.h new file mode 100644 index 00000000..6622f4f8 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.h @@ -0,0 +1,24 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKLabelLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withString:(nullable NSString *)string; ++ (nonnull instancetype)withAttributedString:(nullable NSAttributedString *)attributedString; + +@property (nonatomic, nullable) NSString *string; +@property (nonatomic, nullable) NSAttributedString *attributedString; +@property (nonatomic, nullable) UIFont *font; +@property (nonatomic) NSInteger numberOfLines; +@property (nonatomic) CGFloat lineHeight; + +- (nonnull LOKLabelLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.m new file mode 100644 index 00000000..f65df3d4 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKLabelLayoutBuilder.m @@ -0,0 +1,50 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKLabelLayoutBuilder.h" + +@implementation LOKLabelLayoutBuilder + ++ (nonnull instancetype)withString:(nullable NSString *)string { + LOKLabelLayoutBuilder *builder = [[self alloc] init]; + builder.string = string; + return builder; +} + ++ (nonnull instancetype)withAttributedString:(nullable NSAttributedString *)attributedString { + LOKLabelLayoutBuilder *builder = [[self alloc] init]; + builder.attributedString = attributedString; + return builder; +} + +- (nonnull LOKLabelLayout *)build { + NSAssert(!self.attributedString || !self.string, @"LOKLabelLayoutBuilder should not have both a string and an attributedString."); + if (self.attributedString) { + return [[LOKLabelLayout alloc] initWithAttributedString:self.attributedString + font:self.font + lineHeight:self.lineHeight + numberOfLines:self.numberOfLines + alignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + configure:self.configure]; + } else { + return [[LOKLabelLayout alloc] initWithString:self.string + font:self.font + lineHeight:self.lineHeight + numberOfLines:self.numberOfLines + alignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + configure:self.configure]; + } +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.h new file mode 100644 index 00000000..709fd419 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.h @@ -0,0 +1,21 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKOverlayLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withPrimaryLayout:(nonnull id)primaryLayout; + +@property (nonatomic, nonnull) id primary; +@property (nonatomic, nonnull) NSArray< id > *overlay; +@property (nonatomic, nonnull) NSArray< id > *background; + +- (nonnull LOKOverlayLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.m new file mode 100644 index 00000000..f2079a59 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKOverlayLayoutBuilder.m @@ -0,0 +1,31 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKOverlayLayoutBuilder.h" + +@implementation LOKOverlayLayoutBuilder + ++ (instancetype)withPrimaryLayout:(id)primaryLayout { + LOKOverlayLayoutBuilder *builder = [[self alloc] init]; + builder.primary = primaryLayout; + builder.background = @[]; + builder.overlay = @[]; + return builder; +} + +- (LOKOverlayLayout *)build { + return [[LOKOverlayLayout alloc] initWithPrimary:self.primary + background:self.background + overlay:self.overlay + alignment:self.alignment + viewReuseId:self.viewReuseId + viewClass:self.viewClass + configure:self.configure]; +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.h new file mode 100644 index 00000000..8a332fbc --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.h @@ -0,0 +1,25 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKSizeLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withSublayout:(nullable id)sublayout; + +@property (nonatomic, nullable) id sublayout; +@property (nonatomic) CGFloat minWidth; +@property (nonatomic) CGFloat maxWidth; +@property (nonatomic) CGFloat minHeight; +@property (nonatomic) CGFloat maxHeight; +@property (nonatomic) CGFloat width; +@property (nonatomic) CGFloat height; + +- (nonnull LOKSizeLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.m new file mode 100644 index 00000000..8b9a75f5 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKSizeLayoutBuilder.m @@ -0,0 +1,56 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKSizeLayoutBuilder.h" + +@implementation LOKSizeLayoutBuilder + ++ (instancetype)withSublayout:(id)sublayout { + LOKSizeLayoutBuilder *builder = [[self alloc] init]; + builder.sublayout = sublayout; + builder.minWidth = 0; + builder.minHeight = 0; + builder.maxWidth = INFINITY; + builder.maxHeight = INFINITY; + return builder; +} + +- (CGFloat)width { + NSAssert(self.maxWidth == self.minWidth, @"Can't retrieve a single width property when there's a range set."); + return self.maxWidth; +} + +- (void)setWidth:(CGFloat)width { + self.minWidth = width; + self.maxWidth = width; +} + +- (CGFloat)height { + NSAssert(self.maxHeight == self.minHeight, @"Can't retrieve a singular height property when there's a range set."); + return self.maxHeight; +} + +- (void)setHeight:(CGFloat)height { + self.minHeight = height; + self.maxHeight = height; +} + +- (LOKSizeLayout *)build { + return [[LOKSizeLayout alloc] initWithMinWidth:self.minWidth + maxWidth:self.maxWidth + minHeight:self.minHeight + maxHeight:self.maxHeight + alignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + sublayout:self.sublayout + configure:self.configure]; +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.h new file mode 100644 index 00000000..300dbd5f --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.h @@ -0,0 +1,22 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKStackLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withSublayouts:(nonnull NSArray< id > *)sublayouts; + +@property (nonatomic, nonnull) NSArray< id > *sublayouts; +@property (nonatomic) LOKAxis axis; +@property (nonatomic) CGFloat spacing; +@property (nonatomic) LOKStackLayoutDistribution distribution; + +- (nonnull LOKStackLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.m new file mode 100644 index 00000000..4c4516d4 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKStackLayoutBuilder.m @@ -0,0 +1,32 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKStackLayoutBuilder.h" + +@implementation LOKStackLayoutBuilder + ++ (instancetype)withSublayouts:(NSArray> *)sublayouts { + LOKStackLayoutBuilder *builder = [[self alloc] init]; + builder.axis = LOKAxisVertical; + builder.sublayouts = sublayouts; + return builder; +} + +- (LOKStackLayout *)build { + return [[LOKStackLayout alloc] initWithAxis:self.axis + spacing:self.spacing + distribution:self.distribution + alignment:self.alignment + flexibility:self.flexibility + viewClass:self.viewClass + viewReuseId:self.viewReuseId + sublayouts:self.sublayouts + configure:self.configure]; +} + +@end diff --git a/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.h b/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.h new file mode 100644 index 00000000..3c4dac1a --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.h @@ -0,0 +1,24 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKBaseLayoutBuilder.h" + +@interface LOKTextViewLayoutBuilder : LOKBaseLayoutBuilder + ++ (nonnull instancetype)withString:(nullable NSString *)string; ++ (nonnull instancetype)withAttributedString:(nullable NSAttributedString *)attributedString; + +@property (nonatomic, nullable) NSString *string; +@property (nonatomic, nullable) NSAttributedString *attributedString; +@property (nonatomic, nullable) UIFont *font; +@property (nonatomic) UIEdgeInsets textContainerInset; +@property (nonatomic) CGFloat lineFragmentPadding; + +- (nonnull LOKTextViewLayout *)build; + +@end diff --git a/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.m b/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.m new file mode 100644 index 00000000..6b491aa8 --- /dev/null +++ b/Sources/ObjCSupport/Builders/LOKTextViewLayoutBuilder.m @@ -0,0 +1,50 @@ +// Copyright 2018 LinkedIn Corp. +// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. +// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + +#import "LOKTextViewLayoutBuilder.h" + +@implementation LOKTextViewLayoutBuilder + ++ (nonnull instancetype)withString:(nullable NSString *)string { + LOKTextViewLayoutBuilder *builder = [[self alloc] init]; + builder.string = string; + return builder; +} + ++ (nonnull instancetype)withAttributedString:(nullable NSAttributedString *)attributedString { + LOKTextViewLayoutBuilder *builder = [[self alloc] init]; + builder.attributedString = attributedString; + return builder; +} + +- (nonnull LOKTextViewLayout *)build { + NSAssert(!self.attributedString || !self.string, @"LOKTextViewLayoutBuilder should not have both a string and an attributedString."); + if (self.attributedString) { + return [[LOKTextViewLayout alloc] initWithAttributedText:self.attributedString + font:self.font + lineFragmentPadding:self.lineFragmentPadding + textContainerInset:self.textContainerInset + layoutAlignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + configure:self.configure]; + } else { + return [[LOKTextViewLayout alloc] initWithText:self.string + font:self.font + lineFragmentPadding:self.lineFragmentPadding + textContainerInset:self.textContainerInset + layoutAlignment:self.alignment + flexibility:self.flexibility + viewReuseId:self.viewReuseId + viewClass:self.viewClass + configure:self.configure]; + } +} + +@end