527 lines
17 KiB
Objective-C
527 lines
17 KiB
Objective-C
//
|
|
// CLResizeTool.m
|
|
//
|
|
// Created by sho yakushiji on 2013/12/12.
|
|
// Copyright (c) 2013年 CALACULU. All rights reserved.
|
|
//
|
|
|
|
#import "CLResizeTool.h"
|
|
|
|
static NSString* const kCLResizeToolPresetSizes = @"presetSizes";
|
|
static NSString* const kCLResizeToolLimitSize = @"limitSize";
|
|
static NSString* const kCLResizeToolHorizontalIconName = @"horizontalIconAssetsName";
|
|
static NSString* const kCLResizeToolVerticalIconName = @"verticalIconAssetsName";
|
|
static NSString* const kCLResizeToolChainOnIconName = @"chainOnIconAssetsName";
|
|
static NSString* const kCLResizeToolChainOffIconName = @"chainOffIconAssetsName";
|
|
|
|
@interface _CLResizePanel : UIView
|
|
<UITextFieldDelegate>
|
|
- (id)initWithFrame:(CGRect)frame originalSize:(CGSize)size tool:(CLResizeTool*)tool;
|
|
- (void)setImageWidth:(CGFloat)width;
|
|
- (void)setImageHeight:(CGFloat)height;
|
|
- (void)setLimitSize:(CGFloat)limit;
|
|
- (CGSize)imageSize;
|
|
@end
|
|
|
|
|
|
@implementation CLResizeTool
|
|
{
|
|
UIImage *_originalImage;
|
|
|
|
UIView *_menuContainer;
|
|
CLToolbarMenuItem *_switchBtn;
|
|
UIScrollView *_menuScroll;
|
|
_CLResizePanel *_resizePanel;
|
|
}
|
|
|
|
+ (NSArray*)subtools
|
|
{
|
|
return nil;
|
|
}
|
|
|
|
+ (NSString*)defaultTitle
|
|
{
|
|
return [CLImageEditorTheme localizedString:@"CLResizeTool_DefaultTitle" withDefault:@"Resize"];
|
|
}
|
|
|
|
+ (BOOL)isAvailable
|
|
{
|
|
return ([UIDevice iosVersion] >= 5.0);
|
|
}
|
|
|
|
+ (CGFloat)defaultDockedNumber
|
|
{
|
|
return 5.5;
|
|
}
|
|
|
|
#pragma mark- optional info
|
|
|
|
+ (NSArray*)defaultPresetSizes
|
|
{
|
|
return @[@240, @320, @480, @640, @800, @960, @1024, @2048];
|
|
}
|
|
|
|
+ (NSNumber*)defaultLimitSize
|
|
{
|
|
return @3200;
|
|
}
|
|
|
|
+ (NSDictionary*)optionalInfo
|
|
{
|
|
return @{
|
|
kCLResizeToolPresetSizes:[self defaultPresetSizes],
|
|
kCLResizeToolLimitSize:[self defaultLimitSize],
|
|
kCLResizeToolHorizontalIconName:@"",
|
|
kCLResizeToolVerticalIconName:@"",
|
|
kCLResizeToolChainOnIconName:@"",
|
|
kCLResizeToolChainOffIconName:@"",
|
|
};
|
|
}
|
|
|
|
#pragma mark- implementation
|
|
|
|
- (void)setup
|
|
{
|
|
_originalImage = self.editor.imageView.image;
|
|
|
|
[self.editor fixZoomScaleWithAnimated:YES];
|
|
|
|
_menuContainer = [[UIView alloc] initWithFrame:self.editor.menuView.frame];
|
|
_menuContainer.backgroundColor = self.editor.menuView.backgroundColor;
|
|
[self.editor.view addSubview:_menuContainer];
|
|
|
|
_menuScroll = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, _menuContainer.width - 70, _menuContainer.height)];
|
|
_menuScroll.backgroundColor = [UIColor clearColor];
|
|
_menuScroll.showsHorizontalScrollIndicator = NO;
|
|
_menuScroll.clipsToBounds = NO;
|
|
[_menuContainer addSubview:_menuScroll];
|
|
|
|
UIView *btnPanel = [[UIView alloc] initWithFrame:CGRectMake(_menuScroll.right, 0, 70, _menuContainer.height)];
|
|
btnPanel.backgroundColor = [_menuContainer.backgroundColor colorWithAlphaComponent:0.97];
|
|
[_menuContainer addSubview:btnPanel];
|
|
|
|
_switchBtn = [CLImageEditorTheme menuItemWithFrame:CGRectMake(0, 0, 70, btnPanel.height) target:self action:@selector(pushedSwitchBtn:) toolInfo:nil];
|
|
_switchBtn.tag = 0;
|
|
|
|
_switchBtn.iconImage = [self imageForKey:kCLResizeToolHorizontalIconName defaultImageName:@"btn_width.png"];
|
|
[btnPanel addSubview:_switchBtn];
|
|
|
|
NSNumber *limit = self.toolInfo.optionalInfo[kCLResizeToolLimitSize];
|
|
if(limit==nil){ limit = [self.class defaultLimitSize]; }
|
|
|
|
_resizePanel = [[_CLResizePanel alloc] initWithFrame:self.editor.imageView.superview.frame originalSize:_originalImage.size tool:self];
|
|
_resizePanel.backgroundColor = [[CLImageEditorTheme toolbarColor] colorWithAlphaComponent:0.4];
|
|
[_resizePanel setLimitSize:limit.floatValue];
|
|
[self.editor.view addSubview:_resizePanel];
|
|
|
|
[self setResizeMenu];
|
|
|
|
_menuContainer.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-_menuScroll.top);
|
|
[UIView animateWithDuration:kCLImageToolAnimationDuration
|
|
animations:^{
|
|
self->_menuContainer.transform = CGAffineTransformIdentity;
|
|
}];
|
|
}
|
|
|
|
- (void)cleanup
|
|
{
|
|
[self.editor resetZoomScaleWithAnimated:YES];
|
|
|
|
[_resizePanel endEditing:YES];
|
|
[_resizePanel removeFromSuperview];
|
|
|
|
[UIView animateWithDuration:kCLImageToolAnimationDuration
|
|
animations:^{
|
|
self->_menuContainer.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-self->_menuScroll.top);
|
|
}
|
|
completion:^(BOOL finished) {
|
|
[self->_menuContainer removeFromSuperview];
|
|
}];
|
|
}
|
|
|
|
- (void)executeWithCompletionBlock:(void (^)(UIImage *, NSError *, NSDictionary *))completionBlock
|
|
{
|
|
CGSize size = _resizePanel.imageSize;
|
|
|
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
|
|
if(size.width>0 && size.height>0){
|
|
UIImage *image = [self->_originalImage resize:size];
|
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
completionBlock(image, nil, nil);
|
|
});
|
|
}
|
|
else{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
completionBlock(nil, nil, nil);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
#pragma mark-
|
|
|
|
- (UIImage*)imageWithString:(NSString*)str
|
|
{
|
|
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
|
|
label.textAlignment = NSTextAlignmentCenter;
|
|
label.text = str;
|
|
label.font = [UIFont boldSystemFontOfSize:30];
|
|
label.minimumScaleFactor = 0.5;
|
|
|
|
label.backgroundColor = [[CLImageEditorTheme theme] toolbarTextColor];
|
|
label.textColor = [[CLImageEditorTheme theme] toolbarColor];
|
|
|
|
UIGraphicsBeginImageContextWithOptions(label.frame.size, NO, 0.0);
|
|
[label.layer renderInContext:UIGraphicsGetCurrentContext()];
|
|
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
UIGraphicsEndImageContext();
|
|
|
|
return image;
|
|
}
|
|
|
|
- (void)setResizeMenu
|
|
{
|
|
CGFloat W = 70;
|
|
CGFloat H = _menuScroll.height;
|
|
CGFloat x = 0;
|
|
|
|
NSArray *sizes = self.toolInfo.optionalInfo[kCLResizeToolPresetSizes];
|
|
if(sizes==nil || ![sizes isKindOfClass:[NSArray class]] || sizes.count==0){
|
|
sizes = [[self class] defaultPresetSizes];
|
|
}
|
|
|
|
for(NSNumber *size in sizes){
|
|
CLToolbarMenuItem *view = [CLImageEditorTheme menuItemWithFrame:CGRectMake(x, 0, W, H) target:self action:@selector(tappedResizePanel:) toolInfo:nil];
|
|
view.userInfo = @{@"size":size};
|
|
view.iconImage = [self imageWithString:[NSString stringWithFormat:@"%@", size]];
|
|
|
|
[_menuScroll addSubview:view];
|
|
x += W;
|
|
}
|
|
_menuScroll.contentSize = CGSizeMake(MAX(x, _menuScroll.frame.size.width+1), 0);
|
|
}
|
|
|
|
- (void)pushedSwitchBtn:(UITapGestureRecognizer*)sender
|
|
{
|
|
if(_switchBtn.tag==0){
|
|
_switchBtn.tag = 1;
|
|
_switchBtn.iconImage = [self imageForKey:kCLResizeToolVerticalIconName defaultImageName:@"btn_height.png"];
|
|
}
|
|
else{
|
|
_switchBtn.tag = 0;
|
|
_switchBtn.iconImage = [self imageForKey:kCLResizeToolHorizontalIconName defaultImageName:@"btn_width.png"];
|
|
}
|
|
|
|
_switchBtn.alpha = 0.2;
|
|
[UIView animateWithDuration:kCLImageToolAnimationDuration
|
|
animations:^{
|
|
self->_switchBtn.alpha = 1;
|
|
}
|
|
];
|
|
}
|
|
|
|
- (void)tappedResizePanel:(UITapGestureRecognizer*)sender
|
|
{
|
|
UIView *view = sender.view;
|
|
|
|
NSNumber *size = view.userInfo[@"size"];
|
|
if(size){
|
|
if(_switchBtn.tag==0){
|
|
[_resizePanel setImageWidth:size.floatValue];
|
|
}
|
|
else{
|
|
[_resizePanel setImageHeight:size.floatValue];
|
|
}
|
|
}
|
|
|
|
view.alpha = 0.2;
|
|
[UIView animateWithDuration:kCLImageToolAnimationDuration
|
|
animations:^{
|
|
view.alpha = 1;
|
|
}
|
|
];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
|
|
@implementation _CLResizePanel
|
|
{
|
|
UIView *_infoPanel;
|
|
CGSize _originalSize;
|
|
|
|
CGFloat _limitSize;
|
|
UITextField *_fieldW;
|
|
UITextField *_fieldH;
|
|
|
|
UIButton *_chainBtn;
|
|
}
|
|
|
|
- (id)initWithFrame:(CGRect)frame
|
|
{
|
|
self = [super initWithFrame:frame];
|
|
if(self){
|
|
_infoPanel = [[UIView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width*0.85, 180)];
|
|
_infoPanel.backgroundColor = [[CLImageEditorTheme toolbarColor] colorWithAlphaComponent:0.9];
|
|
_infoPanel.layer.cornerRadius = 5;
|
|
_infoPanel.center = CGPointMake(self.width/2, self.height/2);
|
|
_infoPanel.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin;
|
|
[self addSubview:_infoPanel];
|
|
|
|
[self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidTap:)]];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillChange:) name:UIKeyboardWillShowNotification object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillChange:) name:UIKeyboardWillHideNotification object:nil];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
- (id)initWithFrame:(CGRect)frame originalSize:(CGSize)size tool:(CLResizeTool *)tool
|
|
{
|
|
self = [self initWithFrame:frame];
|
|
if(self){
|
|
_originalSize = size;
|
|
[self initInfoPanelWithTool:tool];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)initInfoPanelWithTool:(CLResizeTool*)tool
|
|
{
|
|
UIFont *font = [CLImageEditorTheme toolbarTextFont];
|
|
|
|
CGFloat y = 0;
|
|
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, _infoPanel.width-20, 30)];
|
|
[label setTextColor:[CLImageEditorTheme toolbarTextColor]];
|
|
label.backgroundColor = [UIColor clearColor];
|
|
label.font = [font fontWithSize:17];
|
|
|
|
label.text = [CLImageEditorTheme localizedString:@"CLResizeTool_InfoPanelTextOriginalSize" withDefault:@"Original Image Size:"];
|
|
[_infoPanel addSubview:label];
|
|
y = label.bottom;
|
|
|
|
label = [[UILabel alloc] initWithFrame:CGRectMake(10, y, _infoPanel.width-20, 50)];
|
|
[label setTextColor:[CLImageEditorTheme toolbarTextColor]];
|
|
label.backgroundColor = [UIColor clearColor];
|
|
label.font = [font fontWithSize:30];
|
|
label.text = [NSString stringWithFormat:@"%ld x %ld", (long)_originalSize.width, (long)_originalSize.height];
|
|
label.textAlignment = NSTextAlignmentCenter;
|
|
[_infoPanel addSubview:label];
|
|
//y = label.bottom;
|
|
|
|
label = [[UILabel alloc] initWithFrame:CGRectMake(10, _infoPanel.height/2, _infoPanel.width-20, 30)];
|
|
[label setTextColor:[CLImageEditorTheme toolbarTextColor]];
|
|
label.backgroundColor = [UIColor clearColor];
|
|
label.font = [font fontWithSize:17];
|
|
label.text = [CLImageEditorTheme localizedString:@"CLResizeTool_InfoPanelTextNewSize" withDefault:@"New Image Size:"];
|
|
[_infoPanel addSubview:label];
|
|
y = label.bottom;
|
|
/*
|
|
label = [[UILabel alloc] initWithFrame:CGRectMake(10, y, _infoPanel.width-20, 50)];
|
|
label.backgroundColor = [UIColor clearColor];
|
|
label.font = [font fontWithSize:30];
|
|
label.text = @"x";
|
|
label.textAlignment = NSTextAlignmentCenter;
|
|
[_infoPanel addSubview:label];
|
|
*/
|
|
_chainBtn = [UIButton buttonWithType:UIButtonTypeCustom];
|
|
_chainBtn.frame = CGRectMake(0, 0, 35, 35);
|
|
_chainBtn.center = CGPointMake(label.center.x, y + 25);
|
|
|
|
[_chainBtn setImage:[tool imageForKey:kCLResizeToolChainOffIconName defaultImageName:@"btn_chain_off.png"] forState:UIControlStateNormal];
|
|
[_chainBtn setImage:[tool imageForKey:kCLResizeToolChainOnIconName defaultImageName:@"btn_chain_on.png"] forState:UIControlStateSelected];
|
|
[_chainBtn addTarget:self action:@selector(chainBtnDidPush:) forControlEvents:UIControlEventTouchUpInside];
|
|
_chainBtn.selected = YES;
|
|
[_infoPanel addSubview:_chainBtn];
|
|
|
|
_fieldW = [[UITextField alloc] initWithFrame:CGRectMake(_chainBtn.left - 110, y+5, 100, 40)];
|
|
[_fieldW setTextColor:[CLImageEditorTheme toolbarTextColor]];
|
|
_fieldW.font = [font fontWithSize:30];
|
|
_fieldW.textAlignment = NSTextAlignmentCenter;
|
|
_fieldW.keyboardType = UIKeyboardTypeNumberPad;
|
|
_fieldW.layer.borderWidth = 1;
|
|
_fieldW.layer.borderColor = [[[CLImageEditorTheme theme] toolbarTextColor] CGColor];
|
|
_fieldW.text = [NSString stringWithFormat:@"%ld", (long)_originalSize.width];
|
|
_fieldW.delegate = self;
|
|
[_fieldW addTarget:self action:@selector(textFieldDidChanged:) forControlEvents:UIControlEventEditingChanged];
|
|
[_infoPanel addSubview:_fieldW];
|
|
|
|
_fieldH = [[UITextField alloc] initWithFrame:CGRectMake(_chainBtn.right + 10, y+5, 100, 40)];
|
|
[_fieldH setTextColor:[CLImageEditorTheme toolbarTextColor]];
|
|
_fieldH.font = [font fontWithSize:30];
|
|
_fieldH.textAlignment = NSTextAlignmentCenter;
|
|
_fieldH.keyboardType = UIKeyboardTypeNumberPad;
|
|
_fieldH.layer.borderWidth = 1;
|
|
_fieldH.layer.borderColor = _fieldW.layer.borderColor;
|
|
_fieldH.text = [NSString stringWithFormat:@"%ld", (long)_originalSize.height];
|
|
_fieldH.delegate = self;
|
|
[_fieldH addTarget:self action:@selector(textFieldDidChanged:) forControlEvents:UIControlEventEditingChanged];
|
|
[_infoPanel addSubview:_fieldH];
|
|
}
|
|
|
|
#pragma mark - gesture events
|
|
|
|
- (void)viewDidTap:(UITapGestureRecognizer*)sender
|
|
{
|
|
[self endEditing:YES];
|
|
}
|
|
|
|
- (void)chainBtnDidPush:(UIButton*)sender
|
|
{
|
|
sender.selected = !sender.selected;
|
|
|
|
CGFloat W = _fieldW.text.floatValue;
|
|
CGFloat H = _fieldH.text.floatValue;
|
|
if(W>H){
|
|
[self setImageWidth:W];
|
|
}
|
|
else{
|
|
[self setImageHeight:H];
|
|
}
|
|
}
|
|
|
|
#pragma mark - keyboard events
|
|
|
|
- (void)keyBoardWillChange:(NSNotification *)notificatioin
|
|
{
|
|
CGRect keyboardFrame = [[notificatioin.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
|
|
keyboardFrame = [self.superview convertRect:keyboardFrame fromView:self.window];
|
|
|
|
UIViewAnimationCurve animationCurve = [[notificatioin.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];
|
|
double duration = [[notificatioin.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
|
|
|
|
[UIView animateWithDuration:duration
|
|
delay:0
|
|
options:UIViewAnimationOptionBeginFromCurrentState | (animationCurve<<16)
|
|
animations:^{
|
|
CGFloat H = MIN(self.height, keyboardFrame.origin.y - self.top);
|
|
self->_infoPanel.center = CGPointMake(self->_infoPanel.center.x, H/2);
|
|
} completion:^(BOOL finished) {
|
|
|
|
}
|
|
];
|
|
}
|
|
|
|
#pragma mark- Size settings
|
|
|
|
- (void)setLimitSize:(CGFloat)limit
|
|
{
|
|
_limitSize = limit;
|
|
[self setImageWidth:_fieldW.text.floatValue];
|
|
}
|
|
|
|
- (void)setImageWidth:(CGFloat)width
|
|
{
|
|
width = MIN(width, _limitSize);
|
|
|
|
if(_chainBtn.selected){
|
|
if(width>0){
|
|
CGFloat height = MAX(1, width * _originalSize.height / _originalSize.width);
|
|
|
|
if(height>_limitSize){
|
|
[self setImageHeight:_limitSize];
|
|
}
|
|
else{
|
|
_fieldW.text = [NSString stringWithFormat:@"%ld", (long)width];
|
|
_fieldH.text = [NSString stringWithFormat:@"%ld", (long)height];
|
|
}
|
|
}
|
|
else{
|
|
_fieldH.text = @"";
|
|
}
|
|
}
|
|
else if(width>0){
|
|
_fieldW.text = [NSString stringWithFormat:@"%ld", (long)width];
|
|
}
|
|
}
|
|
|
|
- (void)setImageHeight:(CGFloat)height
|
|
{
|
|
height = MIN(height, _limitSize);
|
|
|
|
if(_chainBtn.selected){
|
|
if(height>0){
|
|
CGFloat width = MAX(1, height * _originalSize.width / _originalSize.height);
|
|
|
|
if(width>_limitSize){
|
|
[self setImageWidth:_limitSize];
|
|
}
|
|
else{
|
|
_fieldW.text = [NSString stringWithFormat:@"%ld", (long)width];
|
|
_fieldH.text = [NSString stringWithFormat:@"%ld", (long)height];
|
|
}
|
|
}
|
|
else{
|
|
_fieldW.text = @"";
|
|
}
|
|
}
|
|
else if(height>0){
|
|
_fieldH.text = [NSString stringWithFormat:@"%ld", (long)height];
|
|
}
|
|
}
|
|
|
|
- (void)textFieldDidChanged:(id)sender
|
|
{
|
|
if(sender==_fieldW){
|
|
[self setImageWidth:_fieldW.text.floatValue];
|
|
}
|
|
else if(sender==_fieldH){
|
|
[self setImageHeight:_fieldH.text.floatValue];
|
|
}
|
|
}
|
|
|
|
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
|
|
{
|
|
if(textField==_fieldW || textField==_fieldH){
|
|
if((string != nil) && (![@"" isEqualToString:string])){
|
|
const char *c = [string cStringUsingEncoding:NSASCIIStringEncoding];
|
|
if(c[0]==0){ return YES; }
|
|
else if([textField.text length]>=4){ return NO; }
|
|
else {return [self isNumber:string]; }
|
|
}
|
|
}
|
|
return YES;
|
|
}
|
|
|
|
- (BOOL)isNumber:(NSString *)value
|
|
{
|
|
if(value == nil || [@"" isEqualToString:value]){ return NO; }
|
|
|
|
BOOL isNum = NO;
|
|
|
|
for(int i=0; i<[value length]; i++){
|
|
NSString *str = [[value substringFromIndex:i] substringToIndex:1];
|
|
|
|
const char *c = [str cStringUsingEncoding:NSASCIIStringEncoding];
|
|
isNum = ((c!=NULL)&&(c[0]>=0x30)&&(c[0]<=0x39));
|
|
|
|
if(_fieldW.text.length==0 && i==0 && (c!=NULL&&c[0]==0x30)){ isNum = NO; }
|
|
|
|
if(!isNum){ break; }
|
|
}
|
|
|
|
return isNum;
|
|
}
|
|
|
|
- (CGSize)imageSize
|
|
{
|
|
__block CGSize size = CGSizeZero;
|
|
|
|
safe_dispatch_sync_main(^{
|
|
size = CGSizeMake(self->_fieldW.text.floatValue, self->_fieldH.text.floatValue);
|
|
});
|
|
return size;
|
|
}
|
|
|
|
@end
|
|
|