- Add Editor support

This commit is contained in:
giuseppenuc committed 2019-03-10 19:13:51 +01:00
1 parent 5974642e25
commit 1bff59846f
298 files changed
+14488 -1174

No files matched your search

@@ -0,0 +1,30 @@
//
// CLFontPickerView.h
//
// Created by sho yakushiji on 2013/12/14.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol CLFontPickerViewDelegate;
@interface CLFontPickerView : UIView
@property (nonatomic, weak) id<CLFontPickerViewDelegate> delegate;
@property (nonatomic, strong) NSArray *fontList;
@property (nonatomic, strong) NSArray *fontSizes;
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, strong) NSString *text;
@property (nonatomic, assign) BOOL sizeComponentHidden;
@property (nonatomic, strong) UIColor *foregroundColor;
@property (nonatomic, strong) UIColor *textColor;
@end
@protocol CLFontPickerViewDelegate <NSObject>
@optional
- (void)fontPickerView:(CLFontPickerView*)pickerView didSelectFont:(UIFont*)font;
@end
@@ -0,0 +1,211 @@
//
// CLFontPickerView.m
//
// Created by sho yakushiji on 2013/12/14.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLFontPickerView.h"
#import "UIView+Frame.h"
#import "CLPickerView.h"
const CGFloat kCLFontPickerViewConstantFontSize = 14;
@interface CLFontPickerView()
<CLPickerViewDelegate, CLPickerViewDataSource>
@end
@implementation CLFontPickerView
{
CLPickerView *_pickerView;
}
+ (NSArray*)allFontList
{
NSMutableArray *list = [NSMutableArray array];
for(NSString *familyName in [UIFont familyNames]){
for(NSString *fontName in [UIFont fontNamesForFamilyName:familyName]){
[list addObject:[UIFont fontWithName:fontName size:kCLFontPickerViewConstantFontSize]];
}
}
return [list sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"fontName" ascending:YES]]];
}
+ (NSArray*)defaultSizes
{
return @[@8, @10, @12, @14, @16, @18, @20, @24, @28, @32, @38, @44, @50];
}
+ (UIFont*)defaultFont
{
return [UIFont fontWithName:@"HiraKakuProN-W3"size:kCLFontPickerViewConstantFontSize];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.clipsToBounds = YES;
_pickerView = [[CLPickerView alloc] initWithFrame:self.bounds];
_pickerView.center = CGPointMake(self.width/2, self.height/2);
_pickerView.backgroundColor = [UIColor clearColor];
_pickerView.dataSource = self;
_pickerView.delegate = self;
[self addSubview:_pickerView];
self.fontList = [self.class allFontList];
self.fontSizes = [self.class defaultSizes];
self.font = [self.class defaultFont];
self.foregroundColor = [UIColor colorWithWhite:1 alpha:0.8];
self.textColor = [UIColor blackColor];
}
return self;
}
- (void)setForegroundColor:(UIColor *)foregroundColor
{
_pickerView.foregroundColor = foregroundColor;
}
- (UIColor*)foregroundColor
{
return _pickerView.foregroundColor;
}
- (void)setFontList:(NSArray *)fontList
{
if(fontList != _fontList){
_fontList = fontList;
[_pickerView reloadComponent:0];
}
}
- (void)setFontSizes:(NSArray *)fontSizes
{
if(fontSizes != _fontSizes){
_fontSizes = fontSizes;
[_pickerView reloadComponent:1];
}
}
- (void)setFont:(UIFont *)font
{
UIFont *tmp = [font fontWithSize:kCLFontPickerViewConstantFontSize];
NSInteger fontIndex = [self.fontList indexOfObject:tmp];
if(fontIndex==NSNotFound){ fontIndex = 0; }
NSInteger sizeIndex = 0;
for(sizeIndex=0; sizeIndex<self.fontSizes.count; sizeIndex++){
if(font.pointSize<=[self.fontSizes[sizeIndex] floatValue]){
break;
}
}
[_pickerView selectRow:fontIndex inComponent:0 animated:NO];
[_pickerView selectRow:sizeIndex inComponent:1 animated:NO];
}
- (UIFont*)font
{
UIFont *font = self.fontList[[_pickerView selectedRowInComponent:0]];
CGFloat size = [self.fontSizes[[_pickerView selectedRowInComponent:1]] floatValue];
return [font fontWithSize:size];
}
- (void)setSizeComponentHidden:(BOOL)sizeComponentHidden
{
_sizeComponentHidden = sizeComponentHidden;
[_pickerView setNeedsLayout];
}
#pragma mark- UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(CLPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(CLPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
switch (component) {
case 0:
return self.fontList.count;
case 1:
return self.fontSizes.count;
}
return 0;
}
#pragma mark- UIPickerViewDelegate
- (CGFloat)pickerView:(CLPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return self.height/4;
}
- (CGFloat)pickerView:(CLPickerView *)pickerView widthForComponent:(NSInteger)component
{
CGFloat ratio = self.sizeComponentHidden ? 1 : 0.8;
switch (component) {
case 0:
return self.width*ratio;
case 1:
return self.width*(1-ratio);
}
return 0;
}
- (UIView*)pickerView:(CLPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
UILabel *lbl = nil;
if([view isKindOfClass:[UILabel class]]){
lbl = (UILabel*)view;
}
else{
CGFloat W = [self pickerView:pickerView widthForComponent:component];
CGFloat H = [self pickerView:pickerView rowHeightForComponent:component];
CGFloat dx = 10;
lbl = [[UILabel alloc] initWithFrame:CGRectMake(dx, 0, W-2*dx, H)];
lbl.backgroundColor = [UIColor clearColor];
lbl.adjustsFontSizeToFitWidth = YES;
lbl.minimumScaleFactor = 0.5;
lbl.textAlignment = NSTextAlignmentCenter;
lbl.textColor = self.textColor;
}
switch (component) {
case 0:
lbl.font = self.fontList[row];
if(self.text.length>0){
lbl.text = self.text;
}
else{
lbl.text = [NSString stringWithFormat:@"%@", lbl.font.fontName];
}
break;
case 1:
lbl.font = [UIFont systemFontOfSize:kCLFontPickerViewConstantFontSize];
lbl.text = [NSString stringWithFormat:@"%@", self.fontSizes[row]];
break;
default:
break;
}
return lbl;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if([self.delegate respondsToSelector:@selector(fontPickerView:didSelectFont:)]){
[self.delegate fontPickerView:self didSelectFont:self.font];
}
}
@end
@@ -0,0 +1,43 @@
//
// CLPickerDrum.h
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol CLPickerDrumDataSource;
@protocol CLPickerDrumDelegate;
@interface CLPickerDrum : UIView
@property (nonatomic, weak) id<CLPickerDrumDataSource> dataSource;
@property (nonatomic, weak) id<CLPickerDrumDelegate> delegate;
@property (nonatomic, strong) UIColor *foregroundColor;
- (void)reload;
- (void)selectRow:(NSInteger)row animated:(BOOL)animated;
- (NSInteger)selectedRow;
@end
@protocol CLPickerDrumDataSource <NSObject>
@required
- (NSInteger)numberOfRowsInPickerDrum:(CLPickerDrum *)pickerDrum;
@end
@protocol CLPickerDrumDelegate <NSObject>
@optional
- (CGFloat)rowHeightInPickerDrum:(CLPickerDrum *)pickerDrum;
- (UIView*)pickerDrum:(CLPickerDrum *)pickerDrum viewForRow:(NSInteger)row reusingView:(UIView *)view;
- (NSString *)pickerDrum:(CLPickerDrum *)pickerDrum titleForRow:(NSInteger)row;
- (void)pickerDrum:(CLPickerDrum *)pickerDrum didSelectRow:(NSInteger)row;
@end
@@ -0,0 +1,336 @@
//
// CLPickerDrum.m
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLPickerDrum.h"
#import "UIView+Frame.h"
#define MAX_SCROLLABLE_VIEWS 10000
@interface CLPickerDrum()
<UIScrollViewDelegate>
@property (nonatomic, assign) NSInteger centerContentIndex;
@end
@implementation CLPickerDrum
{
CGFloat _VIEW_WIDTH;
CGFloat _VIEW_HEIGHT;
NSInteger _VIEW_NUM;
NSInteger _ROW_NUM;
NSInteger _topContentIndex;
NSInteger _topViewIndex;
NSInteger _bottomViewIndex;
NSInteger _centerViewIndex;
UIImageView *_imageView;
UIScrollView *_scrollView;
BOOL _didLoad;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self customInit];
}
- (void)customInit
{
_didLoad = NO;
_centerContentIndex = 0;
self.foregroundColor = [UIColor colorWithWhite:1 alpha:0.5];
_imageView = [[UIImageView alloc] initWithFrame:self.bounds];
_imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addSubview:_imageView];
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.pagingEnabled = NO;
_scrollView.delegate = self;
[self insertSubview:_scrollView atIndex:0];
}
- (void)setDataSource:(id<CLPickerDrumDataSource>)dataSource
{
if(dataSource != _dataSource){
_dataSource = dataSource;
_didLoad = NO;
}
}
- (void)setDelegate:(id<CLPickerDrumDelegate>)delegate
{
if(delegate != _delegate){
_delegate = delegate;
_didLoad = NO;
}
}
#pragma mark- Build foreground image
- (UIImage*)foregroundImage
{
UIGraphicsBeginImageContextWithOptions(self.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, self.foregroundColor.CGColor);
CGContextFillRect(context, self.bounds);
CGRect rct = CGRectMake(0, (self.height - _VIEW_HEIGHT)/2, self.width, _VIEW_HEIGHT);
CGContextClearRect(context, rct);
UIImage *tmp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tmp;
}
#pragma mark- Instance method
- (void)reload
{
_didLoad = NO;
[self layoutSubviews];
}
- (void)selectRow:(NSInteger)row animated:(BOOL)animated
{
_centerContentIndex = row;
if(_didLoad){
_didLoad = NO;
[self refreshViews];
}
else{
[self layoutSubviews];
}
}
- (NSInteger)selectedRow
{
return self.centerContentIndex;
}
#pragma mark- Info from delegate
- (CGFloat)rowHeight
{
if([self.delegate respondsToSelector:@selector(rowHeightInPickerDrum:)]){
return [self.delegate rowHeightInPickerDrum:self];
}
return ceil(self.height/3.0);
}
- (NSInteger)rowNumberFromIndex:(NSInteger)index
{
NSInteger N = _ROW_NUM;
if(N!=0){ index = (index+N)%N; }
return index;
}
- (UIView*)viewForIndex:(NSInteger)index reusingView:(UIView*)view
{
NSInteger row = [self rowNumberFromIndex:index];
if(row >=0 && row<_ROW_NUM && [self.delegate respondsToSelector:@selector(pickerDrum:viewForRow:reusingView:)]){
return [self.delegate pickerDrum:self viewForRow:row reusingView:view];
}
return nil;
}
- (NSString*)titleForIndex:(NSInteger)index
{
NSInteger row = [self rowNumberFromIndex:index];
if(row >=0 && row<_ROW_NUM && [self.delegate respondsToSelector:@selector(pickerDrum:titleForRow:)]){
return [self.delegate pickerDrum:self titleForRow:row];
}
return @"";
}
#pragma mark- View layout
- (void)layoutSubviews
{
_scrollView.bounds = self.bounds;
_VIEW_NUM = 0;
_VIEW_WIDTH = self.width;
_VIEW_HEIGHT = self.rowHeight;
_ROW_NUM = [self.dataSource numberOfRowsInPickerDrum:self];
_imageView.image = [self foregroundImage];
[self refreshViews];
}
- (void)refreshViews
{
for(UIView *view in _scrollView.subviews){ [view removeFromSuperview]; }
self.centerContentIndex = _centerContentIndex;
NSInteger marginNum = ceil((self.height-_VIEW_HEIGHT)/(2*_VIEW_HEIGHT));
_VIEW_NUM = 2*marginNum + 3;
NSInteger centerIndex = _VIEW_NUM/2;
_scrollView.contentOffset = CGPointMake(0, _VIEW_HEIGHT*MAX_SCROLLABLE_VIEWS/2);
_scrollView.contentSize = CGSizeMake(0, _VIEW_HEIGHT*MAX_SCROLLABLE_VIEWS);
CGRect viewFrame = CGRectMake(0, _scrollView.contentOffset.y+(_scrollView.height-_VIEW_HEIGHT)/2-centerIndex*_VIEW_HEIGHT, _VIEW_WIDTH, _VIEW_HEIGHT);
for(NSInteger i=0; i<_VIEW_NUM; ++i){
UIView *view = [self viewForIndex:i-centerIndex+self.centerContentIndex reusingView:nil];
if(view==nil){
UILabel *label = [UILabel new];
label.textAlignment = NSTextAlignmentCenter;
label.text = [self titleForIndex:i-centerIndex+self.centerContentIndex];
view = label;
}
view.frame = viewFrame;
[_scrollView addSubview:view];
viewFrame.origin.y += _VIEW_HEIGHT;
}
_topContentIndex = MAX_SCROLLABLE_VIEWS/2;
_topViewIndex = 0;
_bottomViewIndex = _VIEW_NUM-1;
_didLoad = YES;
}
#pragma mark- Scrolling
- (void)setCenterContentIndex:(NSInteger)centerContentIndex
{
if(_ROW_NUM>0){
centerContentIndex = (centerContentIndex + _ROW_NUM)%_ROW_NUM;
}
else{
centerContentIndex = 0;
}
if(centerContentIndex != _centerContentIndex){
_centerContentIndex = centerContentIndex;
if([self.delegate respondsToSelector:@selector(pickerDrum:didSelectRow:)]){
[self.delegate pickerDrum:self didSelectRow:_centerContentIndex];
}
}
}
- (NSInteger)calcViewIndex:(NSInteger)index incremental:(NSInteger)incremental
{
return (index + incremental + _VIEW_NUM) % _VIEW_NUM;
}
- (void)scrollWithDirection:(BOOL)upperDirection
{
NSInteger incremental = 0;
NSInteger viewIndex = 0;
NSInteger contentIndex = 0;
if(upperDirection){
incremental = -1;
viewIndex = _bottomViewIndex;
}
else{
incremental = 1;
viewIndex = _topViewIndex;
}
if(viewIndex<_scrollView.subviews.count){
_topContentIndex = _topContentIndex + incremental;
self.centerContentIndex = self.centerContentIndex + incremental;
if(upperDirection){
contentIndex = self.centerContentIndex - _VIEW_NUM/2;
}
else{
contentIndex = self.centerContentIndex - _VIEW_NUM/2 + _VIEW_NUM - 1;
}
UIView *reuse = [_scrollView.subviews objectAtIndex:viewIndex];
UIView *view = [self viewForIndex:contentIndex reusingView:reuse];
if(view==nil){
if([reuse isKindOfClass:[UILabel class]]){
UILabel *label = (UILabel*)reuse;
label.text = [self titleForIndex:contentIndex];
}
}
else if(view!=reuse){
view.frame = reuse.frame;
[reuse removeFromSuperview];
[_scrollView addSubview:view];
reuse = view;
}
reuse.top = reuse.top + _VIEW_HEIGHT * _VIEW_NUM * incremental;
_topViewIndex = [self calcViewIndex:_topViewIndex incremental:incremental];
_bottomViewIndex = [self calcViewIndex:_bottomViewIndex incremental:incremental];
}
}
#pragma UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)sender
{
CGFloat position = sender.contentOffset.y / _VIEW_HEIGHT;
CGFloat delta = position - (CGFloat)_topContentIndex;
NSInteger count = (NSInteger)MAX(fabs(delta-0.5), fabs(delta+0.5));
for(NSInteger i=0; i<count; ++i){
[self scrollWithDirection:(delta<0)];
}
}
- (void)adjustContentOffset
{
[UIView animateWithDuration:0.25
delay:0
options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseInOut
animations:^{
self->_scrollView.contentOffset = CGPointMake(0, self->_VIEW_HEIGHT*self->_topContentIndex);
}
completion:^(BOOL finished) { }
];
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender
{
[self adjustContentOffset];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)sender willDecelerate:(BOOL)decelerate
{
[self adjustContentOffset];
}
@end
@@ -0,0 +1,47 @@
//
// CLPickerView.h
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol CLPickerViewDataSource;
@protocol CLPickerViewDelegate;
@interface CLPickerView : UIView
@property (nonatomic, weak) id<CLPickerViewDataSource> dataSource;
@property (nonatomic, weak) id<CLPickerViewDelegate> delegate;
@property (nonatomic, strong) UIColor *foregroundColor;
- (void)reloadComponent:(NSInteger)component;
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated;
- (NSInteger)selectedRowInComponent:(NSInteger)component;
@end
@protocol CLPickerViewDataSource <NSObject>
@required
- (NSInteger)numberOfComponentsInPickerView:(CLPickerView *)pickerView;
- (NSInteger)pickerView:(CLPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
@end
@protocol CLPickerViewDelegate <NSObject>
@optional
- (CGFloat)pickerView:(CLPickerView *)pickerView widthForComponent:(NSInteger)component;
- (NSString *)pickerView:(CLPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component;
- (UIView *)pickerView:(CLPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view;
- (CGFloat)pickerView:(CLPickerView *)pickerView rowHeightForComponent:(NSInteger)component;
- (void)pickerView:(CLPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
@end
@@ -0,0 +1,182 @@
//
// CLPickerView.m
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLPickerView.h"
#import "UIView+Frame.h"
#import "CLPickerDrum.h"
@interface CLPickerView()
<CLPickerDrumDelegate, CLPickerDrumDataSource>
@end
@implementation CLPickerView
{
NSMutableArray *_drums;
BOOL _didLoad;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self customInit];
}
- (void)customInit
{
_didLoad = NO;
_drums = [NSMutableArray array];
}
- (void)setDataSource:(id<CLPickerViewDataSource>)dataSource
{
if(dataSource != _dataSource){
_dataSource = dataSource;
_didLoad = NO;
}
}
- (void)setDelegate:(id<CLPickerViewDelegate>)delegate
{
if(delegate != _delegate){
_delegate = delegate;
_didLoad = NO;
}
}
#pragma mark- picker info
- (void)reloadComponent:(NSInteger)component
{
if(!_didLoad){ [self layoutSubviews]; }
if(component>=0 && component<_drums.count){
CLPickerDrum *drum = _drums[component];
[drum reload];
}
}
- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated
{
if(!_didLoad){ [self layoutSubviews]; }
if(component>=0 && component<_drums.count){
CLPickerDrum *drum = _drums[component];
[drum selectRow:row animated:animated];
}
}
- (NSInteger)selectedRowInComponent:(NSInteger)component
{
if(component>=0 && component<_drums.count){
CLPickerDrum *drum = _drums[component];
return [drum selectedRow];
}
return 0;
}
#pragma mark- Info from delegate
- (CGFloat)widthForComponent:(NSInteger)component
{
if([self.delegate respondsToSelector:@selector(pickerView:widthForComponent:)]){
return [self.delegate pickerView:self widthForComponent:component];
}
return 0;
}
#pragma mark- View layout
- (void)layoutSubviews
{
NSInteger N = [self.dataSource numberOfComponentsInPickerView:self];
CGFloat x = 0;
for(NSInteger i=0; i<N; ++i){
CGFloat width = [self widthForComponent:i];
if(width==0){ width = self.width / N; }
CLPickerDrum *drum = nil;
if(i<_drums.count){
drum = _drums[i];
}
else{
drum = [[CLPickerDrum alloc] initWithFrame:CGRectMake(x, 0, width, self.height)];
[_drums addObject:drum];
[self addSubview:drum];
}
drum.frame = CGRectMake(x, 0, width, self.height);
drum.tag = i;
drum.backgroundColor = [UIColor clearColor];
drum.foregroundColor = self.foregroundColor;
drum.dataSource = self;
drum.delegate = self;
[drum reload];
x += width;
}
for(NSInteger i=_drums.count-1; i>=N; --i){
CLPickerDrum *drum = [_drums objectAtIndex:i];
[drum removeFromSuperview];
[_drums removeObject:drum];
}
_didLoad = YES;
}
#pragma mark- CLPickerDrum data source
- (NSInteger)numberOfRowsInPickerDrum:(CLPickerDrum *)pickerDrum
{
return [self.dataSource pickerView:self numberOfRowsInComponent:pickerDrum.tag];
}
#pragma mark- CLPickerDrum delegate
- (CGFloat)rowHeightInPickerDrum:(CLPickerDrum *)pickerDrum
{
if([self.delegate respondsToSelector:@selector(pickerView:rowHeightForComponent:)]){
return [self.delegate pickerView:self rowHeightForComponent:pickerDrum.tag];
}
return ceil(self.height / 3);
}
- (UIView*)pickerDrum:(CLPickerDrum *)pickerDrum viewForRow:(NSInteger)row reusingView:(UIView *)view
{
if([self.delegate respondsToSelector:@selector(pickerView:viewForRow:forComponent:reusingView:)]){
return [self.delegate pickerView:self viewForRow:row forComponent:pickerDrum.tag reusingView:view];
}
return nil;
}
- (NSString *)pickerDrum:(CLPickerDrum *)pickerDrum titleForRow:(NSInteger)row
{
if([self.delegate respondsToSelector:@selector(pickerView:titleForRow:forComponent:)]){
return [self.delegate pickerView:self titleForRow:row forComponent:pickerDrum.tag];
}
return [NSString stringWithFormat:@"%ld - %ld", (long)pickerDrum.tag, (long)row];
}
- (void)pickerDrum:(CLPickerDrum *)pickerDrum didSelectRow:(NSInteger)row
{
if([self.delegate respondsToSelector:@selector(pickerView:didSelectRow:inComponent:)]){
[self.delegate pickerView:self didSelectRow:row inComponent:pickerDrum.tag];
}
}
@end
@@ -0,0 +1,15 @@
//
// CLTextLabel.h
//
// Created by sho yakushiji on 2013/12/16.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface CLTextLabel : UILabel
@property (nonatomic, strong) UIColor *outlineColor;
@property (nonatomic, assign) CGFloat outlineWidth;
@end
@@ -0,0 +1,59 @@
//
// CLTextLabel.m
//
// Created by sho yakushiji on 2013/12/16.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLTextLabel.h"
@implementation CLTextLabel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)setOutlineColor:(UIColor *)outlineColor
{
if(outlineColor != _outlineColor){
_outlineColor = outlineColor;
[self setNeedsDisplay];
}
}
- (void)setOutlineWidth:(CGFloat)outlineWidth
{
if(outlineWidth != _outlineWidth){
_outlineWidth = outlineWidth;
[self setNeedsDisplay];
}
}
- (void)drawTextInRect:(CGRect)rect
{
CGSize shadowOffset = self.shadowOffset;
UIColor *txtColor = self.textColor;
CGFloat outlineSize = self.outlineWidth * self.font.pointSize * 0.3;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(contextRef, outlineSize);
CGContextSetLineJoin(contextRef, kCGLineJoinRound);
CGContextSetTextDrawingMode(contextRef, kCGTextStroke);
self.textColor = self.outlineColor;
[super drawTextInRect:CGRectInset(rect, outlineSize/4, outlineSize/4)];
CGContextSetTextDrawingMode(contextRef, kCGTextFill);
self.textColor = txtColor;
[super drawTextInRect:CGRectInset(rect, outlineSize/4, outlineSize/4)];
self.shadowOffset = shadowOffset;
}
@end
@@ -0,0 +1,39 @@
//
// CLTextSettingView.h
//
// Created by sho yakushiji on 2013/12/18.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import <UIKit/UIKit.h>
@protocol CLTextSettingViewDelegate;
@interface CLTextSettingView : UIView
@property (nonatomic, weak) id<CLTextSettingViewDelegate> delegate;
@property (nonatomic, strong) NSString *selectedText;
@property (nonatomic, strong) UIColor *selectedFillColor;
@property (nonatomic, strong) UIColor *selectedBorderColor;
@property (nonatomic, assign) CGFloat selectedBorderWidth;
@property (nonatomic, strong) UIFont *selectedFont;
- (void)setTextColor:(UIColor*)textColor;
- (void)setFontPickerForegroundColor:(UIColor*)foregroundColor;
- (void)showSettingMenuWithIndex:(NSInteger)index animated:(BOOL)animated;
@end
@protocol CLTextSettingViewDelegate <NSObject>
@optional
- (void)textSettingView:(CLTextSettingView*)settingView didChangeText:(NSString*)text;
- (void)textSettingView:(CLTextSettingView*)settingView didChangeFillColor:(UIColor*)fillColor;
- (void)textSettingView:(CLTextSettingView*)settingView didChangeBorderColor:(UIColor*)borderColor;
- (void)textSettingView:(CLTextSettingView*)settingView didChangeBorderWidth:(CGFloat)borderWidth;
- (void)textSettingView:(CLTextSettingView*)settingView didChangeFont:(UIFont*)font;
@end
@@ -0,0 +1,317 @@
//
// CLTextSettingView.m
//
// Created by sho yakushiji on 2013/12/18.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLTextSettingView.h"
#import "UIView+Frame.h"
#import "CLImageEditorTheme.h"
#import "CLColorPickerView.h"
#import "CLFontPickerView.h"
#import "CLCircleView.h"
@interface CLTextSettingView()
<CLColorPickerViewDelegate, CLFontPickerViewDelegate, UITextViewDelegate>
@property (nonatomic, strong) UIView *selectedMode;
@end
@implementation CLTextSettingView
{
UIScrollView *_scrollView;
UITextView *_textView;
CLColorPickerView *_colorPickerView;
CLFontPickerView *_fontPickerView;
UIView *_colorPanel;
CLCircleView *_fillCircle;
CLCircleView *_pathCircle;
UISlider *_pathSlider;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}
- (void)setColorPanel
{
_colorPickerView = [[CLColorPickerView alloc] initWithFrame:CGRectMake(0, 0, 0, 160)];
_colorPickerView.delegate = self;
_colorPickerView.center = CGPointMake(_colorPanel.width/2 - 10, _colorPickerView.height/2 - 5);
[_colorPanel addSubview:_colorPickerView];
_pathSlider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, _colorPickerView.width*0.8, 34)];
_pathSlider.center = CGPointMake(_colorPickerView.center.x, _colorPickerView.bottom + 5);
_pathSlider.minimumValue = 0;
_pathSlider.maximumValue = 1;
_pathSlider.value = 0;
[_pathSlider addTarget:self action:@selector(pathSliderDidChange:) forControlEvents:UIControlEventValueChanged];
[_colorPanel addSubview:_pathSlider];
_pathCircle = [[CLCircleView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];
_pathCircle.right = _colorPanel.width - 10;
_pathCircle.bottom = _pathSlider.center.y;
_pathCircle.radius = 0.6;
_pathCircle.borderWidth = 2;
_pathCircle.borderColor = [UIColor blackColor];
_pathCircle.color = [UIColor clearColor];
[_colorPanel addSubview:_pathCircle];
_fillCircle = [[CLCircleView alloc] initWithFrame:_pathCircle.frame];
_fillCircle.bottom = _pathCircle.top;
_fillCircle.radius = 0.6;
[_colorPanel addSubview:_fillCircle];
[_pathCircle addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(modeViewTapped:)]];
[_fillCircle addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(modeViewTapped:)]];
_fillCircle.tag = 0;
_pathCircle.tag = 1;
self.selectedMode = _fillCircle;
}
- (void)customInit
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBoardWillHide:) name:UIKeyboardWillHideNotification object:nil];
_scrollView = [[UIScrollView alloc] initWithFrame:self.bounds];
_scrollView.pagingEnabled = YES;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.scrollEnabled = NO;
[self addSubview:_scrollView];
_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 0, self.width-42, 80)];
_textView.delegate = self;
_textView.backgroundColor = [UIColor clearColor];
[_scrollView addSubview:_textView];
_colorPanel = [[UIView alloc] initWithFrame:CGRectMake(self.width, 0, self.width, self.height)];
_colorPanel.backgroundColor = [UIColor clearColor];
[_scrollView addSubview:_colorPanel];
[self setColorPanel];
_fontPickerView = [[CLFontPickerView alloc] initWithFrame:CGRectMake(self.width * 2, 0, self.width, self.height)];
_fontPickerView.delegate = self;
_fontPickerView.sizeComponentHidden = YES;
[_scrollView addSubview:_fontPickerView];
_scrollView.contentSize = CGSizeMake(self.width * 3, self.height);
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)setTextColor:(UIColor*)textColor
{
_fontPickerView.textColor = textColor;
_textView.textColor = textColor;
}
- (BOOL)isFirstResponder
{
return _textView.isFirstResponder;
}
- (BOOL)becomeFirstResponder
{
return [_textView becomeFirstResponder];
}
- (BOOL)resignFirstResponder
{
return [_textView resignFirstResponder];
}
- (void)modeViewTapped:(UITapGestureRecognizer*)sender
{
self.selectedMode = sender.view;
}
#pragma mark - Properties
- (void)setSelectedMode:(UIView *)selectedMode
{
if(selectedMode != _selectedMode){
_selectedMode.backgroundColor = [UIColor clearColor];
_selectedMode = selectedMode;
_selectedMode.backgroundColor = [[CLImageEditorTheme theme] toolbarSelectedButtonColor];
if(_selectedMode==_fillCircle){
_colorPickerView.color = _fillCircle.color;
}
else{
_colorPickerView.color = _pathCircle.borderColor;
}
}
}
- (void)setSelectedText:(NSString *)selectedText
{
_textView.text = selectedText;
}
- (NSString*)selectedText
{
return _textView.text;
}
- (void)setSelectedFillColor:(UIColor *)selectedFillColor
{
_fillCircle.color = selectedFillColor;
if(self.selectedMode==_fillCircle){
_colorPickerView.color = _fillCircle.color;
}
}
- (UIColor*)selectedFillColor
{
return _fillCircle.color;
}
- (void)setSelectedBorderColor:(UIColor *)selectedBorderColor
{
_pathCircle.borderColor = selectedBorderColor;
if(self.selectedMode==_pathCircle){
_colorPickerView.color = _pathCircle.borderColor;
}
}
- (UIColor*)selectedBorderColor
{
return _pathCircle.borderColor;
}
- (void)setSelectedBorderWidth:(CGFloat)selectedBorderWidth
{
_pathSlider.value = selectedBorderWidth;
}
- (CGFloat)selectedBorderWidth
{
return _pathSlider.value;
}
- (void)setSelectedFont:(UIFont *)selectedFont
{
_fontPickerView.font = selectedFont;
}
- (UIFont*)selectedFont
{
return _fontPickerView.font;
}
- (void)setFontPickerForegroundColor:(UIColor*)foregroundColor
{
_fontPickerView.foregroundColor = foregroundColor;
}
- (void)showSettingMenuWithIndex:(NSInteger)index animated:(BOOL)animated
{
[_scrollView setContentOffset:CGPointMake(index * self.width, 0) animated:animated];
}
#pragma mark - keyboard events
- (void)keyBoardWillShow:(NSNotification *)notificatioin
{
[self keyBoardWillChange:notificatioin withTextViewHeight:80];
[_textView scrollRangeToVisible:_textView.selectedRange];
}
- (void)keyBoardWillHide:(NSNotification *)notificatioin
{
[self keyBoardWillChange:notificatioin withTextViewHeight:self.height - 20];
}
- (void)keyBoardWillChange:(NSNotification *)notificatioin withTextViewHeight:(CGFloat)height
{
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:^{
self->_textView.height = height;
CGFloat dy = MIN(0, (keyboardFrame.origin.y - self->_textView.height) - self.top);
self.transform = CGAffineTransformMakeTranslation(0, dy);
} completion:^(BOOL finished) {
}
];
}
#pragma mark- Color picker delegate
- (void)colorPickerView:(CLColorPickerView *)picker colorDidChange:(UIColor *)color
{
if(self.selectedMode==_fillCircle){
_fillCircle.color = color;
if([self.delegate respondsToSelector:@selector(textSettingView:didChangeFillColor:)]){
[self.delegate textSettingView:self didChangeFillColor:color];
}
}
else{
_pathCircle.borderColor = color;
if([self.delegate respondsToSelector:@selector(textSettingView:didChangeBorderColor:)]){
[self.delegate textSettingView:self didChangeBorderColor:color];
}
}
}
#pragma mark- PathSlider event
- (void)pathSliderDidChange:(UISlider*)sender
{
if([self.delegate respondsToSelector:@selector(textSettingView:didChangeBorderWidth:)]){
[self.delegate textSettingView:self didChangeBorderWidth:_pathSlider.value];
}
}
#pragma mark- Font picker delegate
- (void)fontPickerView:(CLFontPickerView *)pickerView didSelectFont:(UIFont *)font
{
if([self.delegate respondsToSelector:@selector(textSettingView:didChangeFont:)]){
[self.delegate textSettingView:self didChangeFont:font];
}
}
#pragma mark- UITextView delegate
- (void)textViewDidChange:(UITextView*)textView
{
NSRange selection = textView.selectedRange;
if(selection.location+selection.length == textView.text.length && [textView.text characterAtIndex:textView.text.length-1] == '\n') {
[textView layoutSubviews];
[textView scrollRectToVisible:CGRectMake(0, textView.contentSize.height - 1, 1, 1) animated:YES];
}
else {
[textView scrollRangeToVisible:textView.selectedRange];
}
if([self.delegate respondsToSelector:@selector(textSettingView:didChangeText:)]){
[self.delegate textSettingView:self didChangeText:textView.text];
}
}
@end
@@ -0,0 +1,12 @@
//
// CLTextTool.h
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLImageToolBase.h"
@interface CLTextTool : CLImageToolBase
@end
@@ -0,0 +1,735 @@
//
// CLTextTool.m
//
// Created by sho yakushiji on 2013/12/15.
// Copyright (c) 2013年 CALACULU. All rights reserved.
//
#import "CLTextTool.h"
#import "CLCircleView.h"
#import "CLColorPickerView.h"
#import "CLFontPickerView.h"
#import "CLTextLabel.h"
#import "CLTextSettingView.h"
static NSString* const CLTextViewActiveViewDidChangeNotification = @"CLTextViewActiveViewDidChangeNotificationString";
static NSString* const CLTextViewActiveViewDidTapNotification = @"CLTextViewActiveViewDidTapNotificationString";
static NSString* const kCLTextToolDeleteIconName = @"deleteIconAssetsName";
static NSString* const kCLTextToolCloseIconName = @"closeIconAssetsName";
static NSString* const kCLTextToolNewTextIconName = @"newTextIconAssetsName";
static NSString* const kCLTextToolEditTextIconName = @"editTextIconAssetsName";
static NSString* const kCLTextToolFontIconName = @"fontIconAssetsName";
static NSString* const kCLTextToolAlignLeftIconName = @"alignLeftIconAssetsName";
static NSString* const kCLTextToolAlignCenterIconName = @"alignCenterIconAssetsName";
static NSString* const kCLTextToolAlignRightIconName = @"alignRightIconAssetsName";
@interface _CLTextView : UIView
@property (nonatomic, strong) NSString *text;
@property (nonatomic, strong) UIFont *font;
@property (nonatomic, strong) UIColor *fillColor;
@property (nonatomic, strong) UIColor *borderColor;
@property (nonatomic, assign) CGFloat borderWidth;
@property (nonatomic, assign) NSTextAlignment textAlignment;
+ (void)setActiveTextView:(_CLTextView*)view;
- (id)initWithTool:(CLTextTool*)tool;
- (void)setScale:(CGFloat)scale;
- (void)sizeToFitWithMaxWidth:(CGFloat)width lineHeight:(CGFloat)lineHeight;
@end
@interface CLTextTool()
<CLColorPickerViewDelegate, CLFontPickerViewDelegate, UITextViewDelegate, CLTextSettingViewDelegate>
@property (nonatomic, strong) _CLTextView *selectedTextView;
@end
@implementation CLTextTool
{
UIImage *_originalImage;
UIView *_workingView;
CLTextSettingView *_settingView;
CLToolbarMenuItem *_textBtn;
CLToolbarMenuItem *_colorBtn;
CLToolbarMenuItem *_fontBtn;
CLToolbarMenuItem *_alignLeftBtn;
CLToolbarMenuItem *_alignCenterBtn;
CLToolbarMenuItem *_alignRightBtn;
UIScrollView *_menuScroll;
}
+ (NSArray*)subtools
{
return nil;
}
+ (NSString*)defaultTitle
{
return [CLImageEditorTheme localizedString:@"CLTextTool_DefaultTitle" withDefault:@"Text"];
}
+ (BOOL)isAvailable
{
return ([UIDevice iosVersion] >= 5.0);
}
+ (CGFloat)defaultDockedNumber
{
return 8;
}
#pragma mark- optional info
+ (NSDictionary*)optionalInfo
{
return @{
kCLTextToolDeleteIconName:@"",
kCLTextToolCloseIconName:@"",
kCLTextToolNewTextIconName:@"",
kCLTextToolEditTextIconName:@"",
kCLTextToolFontIconName:@"",
kCLTextToolAlignLeftIconName:@"",
kCLTextToolAlignCenterIconName:@"",
kCLTextToolAlignRightIconName:@"",
};
}
#pragma mark- implementation
- (void)setup
{
_originalImage = self.editor.imageView.image;
[self.editor fixZoomScaleWithAnimated:YES];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(activeTextViewDidChange:) name:CLTextViewActiveViewDidChangeNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(activeTextViewDidTap:) name:CLTextViewActiveViewDidTapNotification object:nil];
_menuScroll = [[UIScrollView alloc] initWithFrame:self.editor.menuView.frame];
_menuScroll.backgroundColor = self.editor.menuView.backgroundColor;
_menuScroll.showsHorizontalScrollIndicator = NO;
[self.editor.view addSubview:_menuScroll];
_workingView = [[UIView alloc] initWithFrame:[self.editor.view convertRect:self.editor.imageView.frame fromView:self.editor.imageView.superview]];
_workingView.clipsToBounds = YES;
[self.editor.view addSubview:_workingView];
_settingView = [[CLTextSettingView alloc] initWithFrame:CGRectMake(0, 0, self.editor.view.width, 180)];
_settingView.top = _menuScroll.top - _settingView.height;
_settingView.backgroundColor = [CLImageEditorTheme toolbarColor];
_settingView.textColor = [CLImageEditorTheme toolbarTextColor];
_settingView.fontPickerForegroundColor = _settingView.backgroundColor;
_settingView.delegate = self;
[self.editor.view addSubview:_settingView];
UIButton *okButton = [UIButton buttonWithType:UIButtonTypeCustom];
[okButton setImage:[self imageForKey:kCLTextToolCloseIconName defaultImageName:@"btn_delete.png"] forState:UIControlStateNormal];
okButton.frame = CGRectMake(_settingView.width-32, 0, 32, 32);
[okButton addTarget:self action:@selector(pushedButton:) forControlEvents:UIControlEventTouchUpInside];
[_settingView addSubview:okButton];
[self setMenu];
self.selectedTextView = nil;
_menuScroll.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-_menuScroll.top);
[UIView animateWithDuration:kCLImageToolAnimationDuration
animations:^{
self->_menuScroll.transform = CGAffineTransformIdentity;
}];
}
- (void)cleanup
{
[self.editor resetZoomScaleWithAnimated:YES];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_settingView endEditing:YES];
[_settingView removeFromSuperview];
[_workingView removeFromSuperview];
[UIView animateWithDuration:kCLImageToolAnimationDuration
animations:^{
self->_menuScroll.transform = CGAffineTransformMakeTranslation(0, self.editor.view.height-self->_menuScroll.top);
}
completion:^(BOOL finished) {
[self->_menuScroll removeFromSuperview];
}];
}
- (void)executeWithCompletionBlock:(void (^)(UIImage *, NSError *, NSDictionary *))completionBlock
{
[_CLTextView setActiveTextView:nil];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
UIImage *image = [self buildImage:self->_originalImage];
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(image, nil, nil);
});
});
}
#pragma mark-
- (UIImage*)buildImage:(UIImage*)image
{
__block CALayer *layer = nil;
__block CGFloat scale = 1;
safe_dispatch_sync_main(^{
scale = image.size.width / self->_workingView.width;
layer = self->_workingView.layer;
});
UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);
[image drawAtPoint:CGPointZero];
CGContextScaleCTM(UIGraphicsGetCurrentContext(), scale, scale);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *tmp = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return tmp;
}
- (void)setMenuBtnEnabled:(BOOL)enabled
{
_textBtn.userInteractionEnabled =
_colorBtn.userInteractionEnabled =
_fontBtn.userInteractionEnabled =
_alignLeftBtn.userInteractionEnabled =
_alignCenterBtn.userInteractionEnabled =
_alignRightBtn.userInteractionEnabled = enabled;
}
- (void)setSelectedTextView:(_CLTextView *)selectedTextView
{
if(selectedTextView != _selectedTextView){
_selectedTextView = selectedTextView;
}
[self setMenuBtnEnabled:(_selectedTextView!=nil)];
if(_selectedTextView==nil){
[self hideSettingView];
_colorBtn.iconView.backgroundColor = _settingView.selectedFillColor;
_alignLeftBtn.selected = _alignCenterBtn.selected = _alignRightBtn.selected = NO;
}
else{
_colorBtn.iconView.backgroundColor = selectedTextView.fillColor;
_colorBtn.iconView.layer.borderColor = selectedTextView.borderColor.CGColor;
_colorBtn.iconView.layer.borderWidth = MAX(2, 10*selectedTextView.borderWidth);
_settingView.selectedText = selectedTextView.text;
_settingView.selectedFillColor = selectedTextView.fillColor;
_settingView.selectedBorderColor = selectedTextView.borderColor;
_settingView.selectedBorderWidth = selectedTextView.borderWidth;
_settingView.selectedFont = selectedTextView.font;
[self setTextAlignment:selectedTextView.textAlignment];
}
}
- (void)activeTextViewDidChange:(NSNotification*)notification
{
self.selectedTextView = notification.object;
}
- (void)activeTextViewDidTap:(NSNotification*)notification
{
[self beginTextEditing];
}
- (void)setMenu
{
CGFloat W = 70;
CGFloat H = _menuScroll.height;
CGFloat x = 0;
NSArray *_menu = @[
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemNew" withDefault:@"New"], @"icon":[self imageForKey:kCLTextToolNewTextIconName defaultImageName:@"btn_add.png"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemText" withDefault:@"Text"], @"icon":[self imageForKey:kCLTextToolEditTextIconName defaultImageName:@"icon.png"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemColor" withDefault:@"Color"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemFont" withDefault:@"Font"], @"icon":[self imageForKey:kCLTextToolFontIconName defaultImageName:@"btn_font.png"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemAlignLeft" withDefault:@" "], @"icon":[self imageForKey:kCLTextToolAlignLeftIconName defaultImageName:@"btn_align_left.png"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemAlignCenter" withDefault:@" "], @"icon":[self imageForKey:kCLTextToolAlignCenterIconName defaultImageName:@"btn_align_center.png"]},
@{@"title":[CLImageEditorTheme localizedString:@"CLTextTool_MenuItemAlignRight" withDefault:@" "], @"icon":[self imageForKey:kCLTextToolAlignRightIconName defaultImageName:@"btn_align_right.png"]},
];
NSInteger tag = 0;
for(NSDictionary *obj in _menu){
CLToolbarMenuItem *view = [CLImageEditorTheme menuItemWithFrame:CGRectMake(x, 0, W, H) target:self action:@selector(tappedMenuPanel:) toolInfo:nil];
view.tag = tag++;
view.title = obj[@"title"];
view.iconImage = obj[@"icon"];
switch (view.tag) {
case 1:
_textBtn = view;
break;
case 2:
_colorBtn = view;
_colorBtn.iconView.layer.borderWidth = 2;
_colorBtn.iconView.layer.borderColor = [[UIColor blackColor] CGColor];
break;
case 3:
_fontBtn = view;
break;
case 4:
_alignLeftBtn = view;
break;
case 5:
_alignCenterBtn = view;
break;
case 6:
_alignRightBtn = view;
break;
}
[_menuScroll addSubview:view];
x += W;
}
_menuScroll.contentSize = CGSizeMake(MAX(x, _menuScroll.frame.size.width+1), 0);
}
- (void)tappedMenuPanel:(UITapGestureRecognizer*)sender
{
UIView *view = sender.view;
switch (view.tag) {
case 0:
[self addNewText];
break;
case 1:
case 2:
case 3:
[self showSettingViewWithMenuIndex:view.tag-1];
break;
case 4:
[self setTextAlignment:NSTextAlignmentLeft];
break;
case 5:
[self setTextAlignment:NSTextAlignmentCenter];
break;
case 6:
[self setTextAlignment:NSTextAlignmentRight];
break;
}
view.alpha = 0.2;
[UIView animateWithDuration:kCLImageToolAnimationDuration
animations:^{
view.alpha = 1;
}
];
}
- (void)addNewText
{
_CLTextView *view = [[_CLTextView alloc] initWithTool:self];
view.fillColor = _settingView.selectedFillColor;
view.borderColor = _settingView.selectedBorderColor;
view.borderWidth = _settingView.selectedBorderWidth;
view.font = _settingView.selectedFont;
CGFloat ratio = MIN( (0.8 * _workingView.width) / view.width, (0.2 * _workingView.height) / view.height);
[view setScale:ratio];
view.center = CGPointMake(_workingView.width/2, view.height/2 + 10);
[_workingView addSubview:view];
[_CLTextView setActiveTextView:view];
[self beginTextEditing];
}
- (void)hideSettingView
{
[_settingView endEditing:YES];
_settingView.hidden = YES;
}
- (void)showSettingViewWithMenuIndex:(NSInteger)index
{
if(_settingView.hidden){
_settingView.hidden = NO;
[_settingView showSettingMenuWithIndex:index animated:NO];
}
else{
[_settingView showSettingMenuWithIndex:index animated:YES];
}
}
- (void)beginTextEditing
{
[self showSettingViewWithMenuIndex:0];
[_settingView becomeFirstResponder];
}
- (void)setTextAlignment:(NSTextAlignment)alignment
{
self.selectedTextView.textAlignment = alignment;
_alignLeftBtn.selected = _alignCenterBtn.selected = _alignRightBtn.selected = NO;
switch (alignment) {
case NSTextAlignmentLeft:
_alignLeftBtn.selected = YES;
break;
case NSTextAlignmentCenter:
_alignCenterBtn.selected = YES;
break;
case NSTextAlignmentRight:
_alignRightBtn.selected = YES;
break;
default:
break;
}
}
- (void)pushedButton:(UIButton*)button
{
if(_settingView.isFirstResponder){
[_settingView resignFirstResponder];
}
else{
[self hideSettingView];
}
}
#pragma mark- Setting view delegate
- (void)textSettingView:(CLTextSettingView *)settingView didChangeText:(NSString *)text
{
// set text
self.selectedTextView.text = text;
[self.selectedTextView sizeToFitWithMaxWidth:0.8*_workingView.width lineHeight:0.2*_workingView.height];
}
- (void)textSettingView:(CLTextSettingView*)settingView didChangeFillColor:(UIColor*)fillColor
{
_colorBtn.iconView.backgroundColor = fillColor;
self.selectedTextView.fillColor = fillColor;
}
- (void)textSettingView:(CLTextSettingView*)settingView didChangeBorderColor:(UIColor*)borderColor
{
_colorBtn.iconView.layer.borderColor = borderColor.CGColor;
self.selectedTextView.borderColor = borderColor;
}
- (void)textSettingView:(CLTextSettingView*)settingView didChangeBorderWidth:(CGFloat)borderWidth
{
_colorBtn.iconView.layer.borderWidth = MAX(2, 10*borderWidth);
self.selectedTextView.borderWidth = borderWidth;
}
- (void)textSettingView:(CLTextSettingView *)settingView didChangeFont:(UIFont *)font
{
self.selectedTextView.font = font;
[self.selectedTextView sizeToFitWithMaxWidth:0.8*_workingView.width lineHeight:0.2*_workingView.height];
}
@end
const CGFloat MAX_FONT_SIZE = 50.0;
#pragma mark- _CLTextView
@implementation _CLTextView
{
CLTextLabel *_label;
UIButton *_deleteButton;
CLCircleView *_circleView;
CGFloat _scale;
CGFloat _arg;
CGPoint _initialPoint;
CGFloat _initialArg;
CGFloat _initialScale;
}
+ (void)setActiveTextView:(_CLTextView*)view
{
static _CLTextView *activeView = nil;
if(view != activeView){
[activeView setAvtive:NO];
activeView = view;
[activeView setAvtive:YES];
[activeView.superview bringSubviewToFront:activeView];
NSNotification *n = [NSNotification notificationWithName:CLTextViewActiveViewDidChangeNotification object:view userInfo:nil];
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:n waitUntilDone:NO];
}
}
- (id)initWithTool:(CLTextTool*)tool
{
self = [super initWithFrame:CGRectMake(0, 0, 132, 132)];
if(self){
_label = [[CLTextLabel alloc] init];
[_label setTextColor:[CLImageEditorTheme toolbarTextColor]];
_label.numberOfLines = 0;
_label.backgroundColor = [UIColor clearColor];
_label.layer.borderColor = [[UIColor blackColor] CGColor];
_label.layer.cornerRadius = 3;
_label.font = [UIFont systemFontOfSize:MAX_FONT_SIZE];
_label.minimumScaleFactor = 1/MAX_FONT_SIZE;
_label.adjustsFontSizeToFitWidth = YES;
_label.textAlignment = NSTextAlignmentCenter;
self.text = @"";
[self addSubview:_label];
CGSize size = [_label sizeThatFits:CGSizeMake(FLT_MAX, FLT_MAX)];
_label.frame = CGRectMake(16, 16, size.width, size.height);
self.frame = CGRectMake(0, 0, size.width + 32, size.height + 32);
_deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_deleteButton setImage:[tool imageForKey:kCLTextToolDeleteIconName defaultImageName:@"btn_delete.png"] forState:UIControlStateNormal];
_deleteButton.frame = CGRectMake(0, 0, 32, 32);
_deleteButton.center = _label.frame.origin;
[_deleteButton addTarget:self action:@selector(pushedDeleteBtn:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_deleteButton];
_circleView = [[CLCircleView alloc] initWithFrame:CGRectMake(0, 0, 32, 32)];
_circleView.center = CGPointMake(_label.width + _label.left, _label.height + _label.top);
_circleView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin;
_circleView.radius = 0.7;
_circleView.color = [UIColor whiteColor];
_circleView.borderColor = [UIColor blackColor];
_circleView.borderWidth = 5;
[self addSubview:_circleView];
_arg = 0;
[self setScale:1];
[self initGestures];
}
return self;
}
- (void)initGestures
{
_label.userInteractionEnabled = YES;
[_label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidTap:)]];
[_label addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:)]];
[_circleView addGestureRecognizer:[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(circleViewDidPan:)]];
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* view= [super hitTest:point withEvent:event];
if(view==self){
return nil;
}
return view;
}
#pragma mark- Properties
- (void)setAvtive:(BOOL)active
{
_deleteButton.hidden = !active;
_circleView.hidden = !active;
_label.layer.borderWidth = (active) ? 1/_scale : 0;
}
- (BOOL)active
{
return !_deleteButton.hidden;
}
- (void)sizeToFitWithMaxWidth:(CGFloat)width lineHeight:(CGFloat)lineHeight
{
self.transform = CGAffineTransformIdentity;
_label.transform = CGAffineTransformIdentity;
CGSize size = [_label sizeThatFits:CGSizeMake(width / (15/MAX_FONT_SIZE), FLT_MAX)];
_label.frame = CGRectMake(16, 16, size.width, size.height);
CGFloat viewW = (_label.width + 32);
CGFloat viewH = _label.font.lineHeight;
CGFloat ratio = MIN(width / viewW, lineHeight / viewH);
[self setScale:ratio];
}
- (void)setScale:(CGFloat)scale
{
_scale = scale;
self.transform = CGAffineTransformIdentity;
_label.transform = CGAffineTransformMakeScale(_scale, _scale);
CGRect rct = self.frame;
rct.origin.x += (rct.size.width - (_label.width + 32)) / 2;
rct.origin.y += (rct.size.height - (_label.height + 32)) / 2;
rct.size.width = _label.width + 32;
rct.size.height = _label.height + 32;
self.frame = rct;
_label.center = CGPointMake(rct.size.width/2, rct.size.height/2);
self.transform = CGAffineTransformMakeRotation(_arg);
_label.layer.borderWidth = 1/_scale;
_label.layer.cornerRadius = 3/_scale;
}
- (void)setFillColor:(UIColor *)fillColor
{
_label.textColor = fillColor;
}
- (UIColor*)fillColor
{
return _label.textColor;
}
- (void)setBorderColor:(UIColor *)borderColor
{
_label.outlineColor = borderColor;
}
- (UIColor*)borderColor
{
return _label.outlineColor;
}
- (void)setBorderWidth:(CGFloat)borderWidth
{
_label.outlineWidth = borderWidth;
}
- (CGFloat)borderWidth
{
return _label.outlineWidth;
}
- (void)setFont:(UIFont *)font
{
_label.font = [font fontWithSize:MAX_FONT_SIZE];
}
- (UIFont*)font
{
return _label.font;
}
- (void)setTextAlignment:(NSTextAlignment)textAlignment
{
_label.textAlignment = textAlignment;
}
- (NSTextAlignment)textAlignment
{
return _label.textAlignment;
}
- (void)setText:(NSString *)text
{
if(![text isEqualToString:_text]){
_text = text;
_label.text = (_text.length>0) ? _text : [CLImageEditorTheme localizedString:@"CLTextTool_EmptyText" withDefault:@"Text"];
}
}
#pragma mark- gesture events
- (void)pushedDeleteBtn:(id)sender
{
_CLTextView *nextTarget = nil;
const NSInteger index = [self.superview.subviews indexOfObject:self];
for(NSInteger i=index+1; i<self.superview.subviews.count; ++i){
UIView *view = [self.superview.subviews objectAtIndex:i];
if([view isKindOfClass:[_CLTextView class]]){
nextTarget = (_CLTextView*)view;
break;
}
}
if(nextTarget==nil){
for(NSInteger i=index-1; i>=0; --i){
UIView *view = [self.superview.subviews objectAtIndex:i];
if([view isKindOfClass:[_CLTextView class]]){
nextTarget = (_CLTextView*)view;
break;
}
}
}
[[self class] setActiveTextView:nextTarget];
[self removeFromSuperview];
}
- (void)viewDidTap:(UITapGestureRecognizer*)sender
{
if(self.active){
NSNotification *n = [NSNotification notificationWithName:CLTextViewActiveViewDidTapNotification object:self userInfo:nil];
[[NSNotificationCenter defaultCenter] performSelectorOnMainThread:@selector(postNotification:) withObject:n waitUntilDone:NO];
}
[[self class] setActiveTextView:self];
}
- (void)viewDidPan:(UIPanGestureRecognizer*)sender
{
[[self class] setActiveTextView:self];
CGPoint p = [sender translationInView:self.superview];
if(sender.state == UIGestureRecognizerStateBegan){
_initialPoint = self.center;
}
self.center = CGPointMake(_initialPoint.x + p.x, _initialPoint.y + p.y);
}
- (void)circleViewDidPan:(UIPanGestureRecognizer*)sender
{
CGPoint p = [sender translationInView:self.superview];
static CGFloat tmpR = 1;
static CGFloat tmpA = 0;
if(sender.state == UIGestureRecognizerStateBegan){
_initialPoint = [self.superview convertPoint:_circleView.center fromView:_circleView.superview];
CGPoint p = CGPointMake(_initialPoint.x - self.center.x, _initialPoint.y - self.center.y);
tmpR = sqrt(p.x*p.x + p.y*p.y);
tmpA = atan2(p.y, p.x);
_initialArg = _arg;
_initialScale = _scale;
}
p = CGPointMake(_initialPoint.x + p.x - self.center.x, _initialPoint.y + p.y - self.center.y);
CGFloat R = sqrt(p.x*p.x + p.y*p.y);
CGFloat arg = atan2(p.y, p.x);
_arg = _initialArg + arg - tmpA;
[self setScale:MAX(_initialScale * R / tmpR, 15/MAX_FONT_SIZE)];
}
@end