Skip to content

Commit 83298c5

Browse files
authored
Merge pull request #608 from glyuck/aspect_ratio_preset_class
Move TOCropViewControllerAspectRatioPreset to a class and make it configurable
2 parents 05bc498 + 9c65608 commit 83298c5

File tree

9 files changed

+173
-139
lines changed

9 files changed

+173
-139
lines changed

Objective-C/TOCropViewController/Constants/TOCropViewConstants.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,6 @@ typedef NS_ENUM(NSInteger, TOCropViewCroppingStyle) {
3030
TOCropViewCroppingStyleCircular // A fixed, circular crop box
3131
};
3232

33-
/**
34-
Preset values of the most common aspect ratios that can be used to quickly configure
35-
the crop view controller.
36-
*/
37-
typedef NS_ENUM(NSInteger, TOCropViewControllerAspectRatioPreset) {
38-
TOCropViewControllerAspectRatioPresetOriginal,
39-
TOCropViewControllerAspectRatioPresetSquare,
40-
TOCropViewControllerAspectRatioPreset3x2,
41-
TOCropViewControllerAspectRatioPreset5x3,
42-
TOCropViewControllerAspectRatioPreset4x3,
43-
TOCropViewControllerAspectRatioPreset5x4,
44-
TOCropViewControllerAspectRatioPreset7x5,
45-
TOCropViewControllerAspectRatioPreset16x9,
46-
TOCropViewControllerAspectRatioPresetCustom
47-
};
48-
4933
/**
5034
Whether the control toolbar is placed at the bottom or the top
5135
*/
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// TOCropViewControllerAspectRatioPreset.h
3+
//
4+
// Copyright 2015-2024 Timothy Oliver. All rights reserved.
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to
8+
// deal in the Software without restriction, including without limitation the
9+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10+
// sell copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21+
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
23+
#import <Foundation/Foundation.h>
24+
#import <UIKit/UIKit.h>
25+
26+
NS_ASSUME_NONNULL_BEGIN
27+
28+
@interface TOCropViewControllerAspectRatioPreset : NSObject
29+
30+
@property (nonatomic, readonly) CGSize size;
31+
@property (nonatomic, readonly) NSString *title;
32+
33+
+ (NSArray<TOCropViewControllerAspectRatioPreset *> *)portraitPresets;
34+
+ (NSArray<TOCropViewControllerAspectRatioPreset *> *)landscapePresets;
35+
36+
- (nonnull instancetype)initWithSize:(CGSize)size title:(NSString *)title;
37+
38+
@end
39+
40+
NS_ASSUME_NONNULL_END
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// TOCropViewControllerAspectRatioPreset.m
3+
//
4+
// Copyright 2015-2024 Timothy Oliver. All rights reserved.
5+
//
6+
// Permission is hereby granted, free of charge, to any person obtaining a copy
7+
// of this software and associated documentation files (the "Software"), to
8+
// deal in the Software without restriction, including without limitation the
9+
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10+
// sell copies of the Software, and to permit persons to whom the Software is
11+
// furnished to do so, subject to the following conditions:
12+
//
13+
// The above copyright notice and this permission notice shall be included in
14+
// all copies or substantial portions of the Software.
15+
//
16+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20+
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
21+
// IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22+
23+
#import "TOCropViewControllerAspectRatioPreset.h"
24+
#if !__has_include(<TOCropViewController/TOCropViewConstants.h>)
25+
#import "TOCropViewConstants.h"
26+
#else
27+
#import <TOCropViewController/TOCropViewConstants.h>
28+
#endif
29+
30+
@interface TOCropViewControllerAspectRatioPreset ()
31+
32+
@property (nonatomic, assign, readwrite) CGFloat width;
33+
@property (nonatomic, assign, readwrite) CGFloat height;
34+
@property (nonatomic, strong, readwrite) NSString *title;
35+
36+
@end
37+
38+
@implementation TOCropViewControllerAspectRatioPreset
39+
40+
- (instancetype)initWithSize:(CGSize)size title:(NSString *)title
41+
{
42+
self = [super init];
43+
if (self) {
44+
_size = size;
45+
_title = title;
46+
}
47+
return self;
48+
}
49+
50+
- (BOOL)isEqual:(id)object {
51+
if (self == object) {
52+
return YES;
53+
}
54+
if (![object isKindOfClass:[TOCropViewControllerAspectRatioPreset class]]) {
55+
return NO;
56+
}
57+
TOCropViewControllerAspectRatioPreset *other = (TOCropViewControllerAspectRatioPreset *)object;
58+
return CGSizeEqualToSize(self.size, other.size) && [self.title isEqualToString:other.title];
59+
}
60+
61+
+ (NSArray<TOCropViewControllerAspectRatioPreset *> *)portraitPresets
62+
{
63+
TOCropViewControllerAspectRatioPreset *object = [[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeZero title:@"Original"];
64+
NSBundle *resourceBundle = TO_CROP_VIEW_RESOURCE_BUNDLE_FOR_OBJECT(object);
65+
return @[
66+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeZero title:NSLocalizedStringFromTableInBundle(@"Original", @"TOCropViewControllerLocalizable", resourceBundle, nil)],
67+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(1.0f, 1.0f) title:NSLocalizedStringFromTableInBundle(@"Square", @"TOCropViewControllerLocalizable", resourceBundle, nil)],
68+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(2.0f, 3.0f) title:@"2:3"],
69+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(3.0f, 5.0f) title:@"3:5"],
70+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(3.0f, 4.0f) title:@"3:4"],
71+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(4.0f, 5.0f) title:@"4:5"],
72+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(5.0f, 7.0f) title:@"5:7"],
73+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(9.0f, 16.0f) title:@"9:16"],
74+
];
75+
}
76+
77+
+ (NSArray<TOCropViewControllerAspectRatioPreset *> *)landscapePresets
78+
{
79+
TOCropViewControllerAspectRatioPreset *object = [[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeZero title:@"Original"];
80+
NSBundle *resourceBundle = TO_CROP_VIEW_RESOURCE_BUNDLE_FOR_OBJECT(object);
81+
return @[
82+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeZero title:NSLocalizedStringFromTableInBundle(@"Original", @"TOCropViewControllerLocalizable", resourceBundle, nil)],
83+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(1.0f, 1.0f) title:NSLocalizedStringFromTableInBundle(@"Square", @"TOCropViewControllerLocalizable", resourceBundle, nil)],
84+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(3.0f, 2.0f) title:@"3:2"],
85+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(5.0f, 3.0f) title:@"5:3"],
86+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(4.0f, 3.0f) title:@"4:3"],
87+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(5.0f, 4.0f) title:@"5:4"],
88+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(7.0f, 5.0f) title:@"7:5"],
89+
[[TOCropViewControllerAspectRatioPreset alloc] initWithSize:CGSizeMake(16.0f, 9.0f) title:@"16:9"],
90+
];
91+
}
92+
@end
93+
94+

Objective-C/TOCropViewController/TOCropViewController.h

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,12 @@
2424

2525
#if !__has_include(<TOCropViewController/TOCropViewConstants.h>)
2626
#import "TOCropViewConstants.h"
27+
#import "TOCropViewControllerAspectRatioPreset.h"
2728
#import "TOCropView.h"
2829
#import "TOCropToolbar.h"
2930
#else
3031
#import <TOCropViewController/TOCropViewConstants.h>
32+
#import <TOCropViewController/TOCropViewControllerAspectRatioPreset.h>
3133
#import <TOCropViewController/TOCropView.h>
3234
#import <TOCropViewController/TOCropToolbar.h>
3335
#endif
@@ -150,19 +152,7 @@
150152
/**
151153
A choice from one of the pre-defined aspect ratio presets
152154
*/
153-
@property (nonatomic, assign) TOCropViewControllerAspectRatioPreset aspectRatioPreset;
154-
155-
/**
156-
A CGSize value representing a custom aspect ratio, not listed in the presets.
157-
E.g. A ratio of 4:3 would be represented as (CGSize){4.0f, 3.0f}
158-
*/
159-
@property (nonatomic, assign) CGSize customAspectRatio;
160-
161-
/**
162-
If this is set alongside `customAspectRatio`, the custom aspect ratio
163-
will be shown as a selectable choice in the list of aspect ratios. (Default is `nil`)
164-
*/
165-
@property (nullable, nonatomic, copy) NSString *customAspectRatioName;
155+
@property (nonatomic, assign) CGSize aspectRatioPreset;
166156

167157
/**
168158
Title label which can be used to show instruction on the top of the crop view controller
@@ -324,7 +314,7 @@
324314
An array of `TOCropViewControllerAspectRatioPreset` enum values denoting which
325315
aspect ratios the crop view controller may display (Default is nil. All are shown)
326316
*/
327-
@property (nullable, nonatomic, strong) NSArray<NSNumber *> *allowedAspectRatios;
317+
@property (nullable, nonatomic, strong) NSArray<TOCropViewControllerAspectRatioPreset *> *allowedAspectRatios;
328318

329319
/**
330320
When the user hits cancel, or completes a
@@ -402,7 +392,7 @@
402392
@param aspectRatioPreset The aspect ratio preset
403393
@param animated Whether the transition to the aspect ratio is animated
404394
*/
405-
- (void)setAspectRatioPreset:(TOCropViewControllerAspectRatioPreset)aspectRatioPreset animated:(BOOL)animated NS_SWIFT_NAME(setAspectRatioPreset(_:animated:));
395+
- (void)setAspectRatioPreset:(CGSize)aspectRatioPreset animated:(BOOL)animated NS_SWIFT_NAME(setAspectRatioPreset(_:animated:));
406396

407397
/**
408398
Play a custom animation of the target image zooming to its position in

Objective-C/TOCropViewController/TOCropViewController.m

Lines changed: 10 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ - (instancetype)initWithCroppingStyle:(TOCropViewCroppingStyle)style image:(UIIm
9090
_transitionController = [[TOCropViewControllerTransitioning alloc] init];
9191

9292
// Default initial behaviour
93-
_aspectRatioPreset = TOCropViewControllerAspectRatioPresetOriginal;
93+
_aspectRatioPreset = CGSizeZero;
9494

9595
#if TARGET_OS_MACCATALYST
9696
_toolbarPosition = TOCropViewControllerToolbarPositionTop;
@@ -170,7 +170,7 @@ - (void)viewWillAppear:(BOOL)animated
170170

171171
// If an initial aspect ratio was set before presentation, set it now once the rest of
172172
// the setup will have been done
173-
if (self.aspectRatioPreset != TOCropViewControllerAspectRatioPresetOriginal) {
173+
if (!CGSizeEqualToSize(self.aspectRatioPreset, CGSizeZero)) {
174174
[self setAspectRatioPreset:self.aspectRatioPreset animated:NO];
175175
}
176176
}
@@ -571,50 +571,28 @@ - (void)showAspectRatioDialog
571571

572572
//Prepare the localized options
573573
NSString *cancelButtonTitle = NSLocalizedStringFromTableInBundle(@"Cancel", @"TOCropViewControllerLocalizable", resourceBundle, nil);
574-
NSString *originalButtonTitle = NSLocalizedStringFromTableInBundle(@"Original", @"TOCropViewControllerLocalizable", resourceBundle, nil);
575-
NSString *squareButtonTitle = NSLocalizedStringFromTableInBundle(@"Square", @"TOCropViewControllerLocalizable", resourceBundle, nil);
576574

577575
//Prepare the list that will be fed to the alert view/controller
578-
579-
// Ratio titles according to the order of enum TOCropViewControllerAspectRatioPreset
580-
NSArray<NSString *> *portraitRatioTitles = @[originalButtonTitle, squareButtonTitle, @"2:3", @"3:5", @"3:4", @"4:5", @"5:7", @"9:16"];
581-
NSArray<NSString *> *landscapeRatioTitles = @[originalButtonTitle, squareButtonTitle, @"3:2", @"5:3", @"4:3", @"5:4", @"7:5", @"16:9"];
582576

583-
NSMutableArray *ratioValues = [NSMutableArray array];
584-
NSMutableArray *itemStrings = [NSMutableArray array];
577+
NSArray<TOCropViewControllerAspectRatioPreset *> *presets;
585578

586579
if (self.allowedAspectRatios == nil) {
587-
for (NSInteger i = 0; i < TOCropViewControllerAspectRatioPresetCustom; i++) {
588-
NSString *itemTitle = verticalCropBox ? portraitRatioTitles[i] : landscapeRatioTitles[i];
589-
[itemStrings addObject:itemTitle];
590-
[ratioValues addObject:@(i)];
591-
}
580+
presets = verticalCropBox ? [TOCropViewControllerAspectRatioPreset portraitPresets] : [TOCropViewControllerAspectRatioPreset landscapePresets];
592581
}
593582
else {
594-
for (NSNumber *allowedRatio in self.allowedAspectRatios) {
595-
TOCropViewControllerAspectRatioPreset ratio = allowedRatio.integerValue;
596-
NSString *itemTitle = verticalCropBox ? portraitRatioTitles[ratio] : landscapeRatioTitles[ratio];
597-
[itemStrings addObject:itemTitle];
598-
[ratioValues addObject:allowedRatio];
599-
}
600-
}
601-
602-
// If a custom aspect ratio is provided, and a custom name has been given to it, add it as a visible choice
603-
if (self.customAspectRatioName.length > 0 && !CGSizeEqualToSize(CGSizeZero, self.customAspectRatio)) {
604-
[itemStrings addObject:self.customAspectRatioName];
605-
[ratioValues addObject:@(TOCropViewControllerAspectRatioPresetCustom)];
583+
presets = self.allowedAspectRatios;
606584
}
607585

608586
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
609587
[alertController addAction:[UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleCancel handler:nil]];
610588

611589
//Add each item to the alert controller
612-
for (NSInteger i = 0; i < itemStrings.count; i++) {
590+
for (NSInteger i = 0; i < presets.count; i++) {
613591
id handlerBlock = ^(UIAlertAction *action) {
614-
[self setAspectRatioPreset:[ratioValues[i] integerValue] animated:YES];
592+
[self setAspectRatioPreset:presets[i].size animated:YES];
615593
self.aspectRatioLockEnabled = YES;
616594
};
617-
UIAlertAction *action = [UIAlertAction actionWithTitle:itemStrings[i] style:UIAlertActionStyleDefault handler:handlerBlock];
595+
UIAlertAction *action = [UIAlertAction actionWithTitle:presets[i].title style:UIAlertActionStyleDefault handler:handlerBlock];
618596
[alertController addAction:action];
619597
}
620598

@@ -625,58 +603,10 @@ - (void)showAspectRatioDialog
625603
[self presentViewController:alertController animated:YES completion:nil];
626604
}
627605

628-
- (void)setAspectRatioPreset:(TOCropViewControllerAspectRatioPreset)aspectRatioPreset animated:(BOOL)animated
606+
- (void)setAspectRatioPreset:(CGSize)aspectRatioPreset animated:(BOOL)animated
629607
{
630-
CGSize aspectRatio = CGSizeZero;
631-
632608
_aspectRatioPreset = aspectRatioPreset;
633-
634-
switch (aspectRatioPreset) {
635-
case TOCropViewControllerAspectRatioPresetOriginal:
636-
aspectRatio = CGSizeZero;
637-
break;
638-
case TOCropViewControllerAspectRatioPresetSquare:
639-
aspectRatio = CGSizeMake(1.0f, 1.0f);
640-
break;
641-
case TOCropViewControllerAspectRatioPreset3x2:
642-
aspectRatio = CGSizeMake(3.0f, 2.0f);
643-
break;
644-
case TOCropViewControllerAspectRatioPreset5x3:
645-
aspectRatio = CGSizeMake(5.0f, 3.0f);
646-
break;
647-
case TOCropViewControllerAspectRatioPreset4x3:
648-
aspectRatio = CGSizeMake(4.0f, 3.0f);
649-
break;
650-
case TOCropViewControllerAspectRatioPreset5x4:
651-
aspectRatio = CGSizeMake(5.0f, 4.0f);
652-
break;
653-
case TOCropViewControllerAspectRatioPreset7x5:
654-
aspectRatio = CGSizeMake(7.0f, 5.0f);
655-
break;
656-
case TOCropViewControllerAspectRatioPreset16x9:
657-
aspectRatio = CGSizeMake(16.0f, 9.0f);
658-
break;
659-
case TOCropViewControllerAspectRatioPresetCustom:
660-
aspectRatio = self.customAspectRatio;
661-
break;
662-
}
663-
664-
// If the aspect ratio lock is not enabled, allow a swap
665-
// If the aspect ratio lock is on, allow a aspect ratio swap
666-
// only if the allowDimensionSwap option is specified.
667-
BOOL aspectRatioCanSwapDimensions = !self.aspectRatioLockEnabled ||
668-
(self.aspectRatioLockEnabled && self.aspectRatioLockDimensionSwapEnabled);
669-
670-
//If the image is a portrait shape, flip the aspect ratio to match
671-
if (self.cropView.cropBoxAspectRatioIsPortrait &&
672-
aspectRatioCanSwapDimensions)
673-
{
674-
CGFloat width = aspectRatio.width;
675-
aspectRatio.width = aspectRatio.height;
676-
aspectRatio.height = width;
677-
}
678-
679-
[self.cropView setAspectRatio:aspectRatio animated:animated];
609+
[self.cropView setAspectRatio:aspectRatioPreset animated:animated];
680610
}
681611

682612
- (void)rotateCropViewClockwise
@@ -1200,12 +1130,6 @@ - (void)setResetAspectRatioEnabled:(BOOL)resetAspectRatioEnabled
12001130
}
12011131
}
12021132

1203-
- (void)setCustomAspectRatio:(CGSize)customAspectRatio
1204-
{
1205-
_customAspectRatio = customAspectRatio;
1206-
[self setAspectRatioPreset:TOCropViewControllerAspectRatioPresetCustom animated:NO];
1207-
}
1208-
12091133
- (BOOL)resetAspectRatioEnabled
12101134
{
12111135
return self.cropView.resetAspectRatioEnabled;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../Models/TOCropViewControllerAspectRatioPreset.h

Swift/CropViewController/CropViewController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#import "TOCropView.h"
2727
#import "TOCropToolbar.h"
2828
#import "TOCropViewConstants.h"
29+
#import "TOCropViewControllerAspectRatioPreset.h"
2930
#import "UIImage+CropRotate.h"
3031

3132
FOUNDATION_EXPORT double CropViewControllerVersionNumber;

0 commit comments

Comments
 (0)