mirror of
https://github.com/danog/Telegram.git
synced 2024-12-03 09:57:46 +01:00
501 lines
20 KiB
Objective-C
501 lines
20 KiB
Objective-C
#import "TGPhotoToolbarView.h"
|
|
|
|
#import "TGModernButtonView.h"
|
|
#import "TGPhotoEditorButton.h"
|
|
|
|
@interface TGPhotoToolbarView ()
|
|
{
|
|
UIView *_backgroundView;
|
|
|
|
UIView *_buttonsWrapperView;
|
|
TGModernButton *_cancelButton;
|
|
TGModernButton *_doneButton;
|
|
|
|
CGFloat _landscapeSize;
|
|
|
|
UILongPressGestureRecognizer *_longPressGestureRecognizer;
|
|
}
|
|
@end
|
|
|
|
@implementation TGPhotoToolbarView
|
|
|
|
- (instancetype)initWithBackButtonTitle:(NSString *)backButtonTitle doneButtonTitle:(NSString *)doneButtonTitle accentedDone:(bool)accentedDone solidBackground:(bool)solidBackground
|
|
{
|
|
self = [super initWithFrame:CGRectZero];
|
|
if (self != nil)
|
|
{
|
|
self.clipsToBounds = true;
|
|
|
|
_backgroundView = [[UIView alloc] initWithFrame:CGRectZero];
|
|
_backgroundView.backgroundColor = (solidBackground ? [TGPhotoEditorInterfaceAssets toolbarBackgroundColor] : [TGPhotoEditorInterfaceAssets toolbarTransparentBackgroundColor]);
|
|
[self addSubview:_backgroundView];
|
|
|
|
_buttonsWrapperView = [[UIView alloc] initWithFrame:_backgroundView.bounds];
|
|
[_backgroundView addSubview:_buttonsWrapperView];
|
|
|
|
_cancelButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 60, 44)];
|
|
_cancelButton.exclusiveTouch = true;
|
|
[_cancelButton setTitle:backButtonTitle forState:UIControlStateNormal];
|
|
[_cancelButton setTitleColor:[UIColor whiteColor]];
|
|
_cancelButton.titleLabel.font = TGSystemFontOfSize(17);
|
|
_cancelButton.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
|
|
[_cancelButton sizeToFit];
|
|
_cancelButton.frame = CGRectMake(0, 0.5f, MAX(60.0f, _cancelButton.frame.size.width), 44);
|
|
_cancelButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
|
[_cancelButton addTarget:self action:@selector(cancelButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
[_backgroundView addSubview:_cancelButton];
|
|
|
|
_doneButton = [[TGModernButton alloc] initWithFrame:CGRectMake(0, 0, 40, 44)];
|
|
_doneButton.exclusiveTouch = true;
|
|
[_doneButton setTitle:doneButtonTitle forState:UIControlStateNormal];
|
|
[_doneButton setTitleColor:(accentedDone ? [TGPhotoEditorInterfaceAssets accentColor] : [UIColor whiteColor])];
|
|
_doneButton.titleLabel.font = TGMediumSystemFontOfSize(17);
|
|
_doneButton.contentEdgeInsets = UIEdgeInsetsMake(0, 27, 0, 10);
|
|
[_doneButton sizeToFit];
|
|
CGFloat doneButtonWidth = MAX(40, _doneButton.frame.size.width);
|
|
_doneButton.frame = CGRectMake(self.frame.size.width - doneButtonWidth, 0.5f, doneButtonWidth, 44);
|
|
_doneButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
|
|
[_doneButton addTarget:self action:@selector(doneButtonPressed) forControlEvents:UIControlEventTouchUpInside];
|
|
[_backgroundView addSubview:_doneButton];
|
|
|
|
_longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(doneButtonLongPressed:)];
|
|
_longPressGestureRecognizer.minimumPressDuration = 0.65;
|
|
[_doneButton addGestureRecognizer:_longPressGestureRecognizer];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (TGPhotoEditorButton *)buttonForTab:(TGPhotoEditorTab)editorTab
|
|
{
|
|
TGPhotoEditorButton *button = [[TGPhotoEditorButton alloc] initWithFrame:CGRectMake(0, 0, 28, 28)];
|
|
button.tag = editorTab;
|
|
[button addTarget:self action:@selector(tabButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
|
|
|
|
switch (editorTab)
|
|
{
|
|
case TGPhotoEditorCaptionTab:
|
|
button.iconImage = [TGPhotoEditorInterfaceAssets captionIcon];
|
|
button.dontHighlightOnSelection = true;
|
|
break;
|
|
|
|
case TGPhotoEditorCropTab:
|
|
button.iconImage = [TGPhotoEditorInterfaceAssets cropIcon];
|
|
break;
|
|
|
|
case TGPhotoEditorToolsTab:
|
|
button.iconImage = [TGPhotoEditorInterfaceAssets toolsIcon];
|
|
break;
|
|
|
|
case TGPhotoEditorRotateTab:
|
|
button.iconImage = [TGPhotoEditorInterfaceAssets rotateIcon];
|
|
button.dontHighlightOnSelection = true;
|
|
break;
|
|
|
|
default:
|
|
button = nil;
|
|
break;
|
|
}
|
|
|
|
return button;
|
|
}
|
|
|
|
- (void)setToolbarTabs:(TGPhotoEditorTab)tabs animated:(bool)animated
|
|
{
|
|
if (tabs == _currentTabs)
|
|
return;
|
|
|
|
UIView *transitionView = nil;
|
|
if (animated && _currentTabs != TGPhotoEditorNoneTab)
|
|
{
|
|
transitionView = [_buttonsWrapperView snapshotViewAfterScreenUpdates:false];
|
|
transitionView.frame = _buttonsWrapperView.frame;
|
|
[_buttonsWrapperView.superview addSubview:transitionView];
|
|
}
|
|
|
|
_currentTabs = tabs;
|
|
|
|
NSArray *buttons = [_buttonsWrapperView.subviews copy];
|
|
for (UIView *view in buttons)
|
|
[view removeFromSuperview];
|
|
|
|
if (_currentTabs & TGPhotoEditorCaptionTab)
|
|
[_buttonsWrapperView addSubview:[self buttonForTab:TGPhotoEditorCaptionTab]];
|
|
if (_currentTabs & TGPhotoEditorCropTab)
|
|
[_buttonsWrapperView addSubview:[self buttonForTab:TGPhotoEditorCropTab]];
|
|
if (_currentTabs & TGPhotoEditorToolsTab)
|
|
[_buttonsWrapperView addSubview:[self buttonForTab:TGPhotoEditorToolsTab]];
|
|
if (_currentTabs & TGPhotoEditorRotateTab)
|
|
[_buttonsWrapperView addSubview:[self buttonForTab:TGPhotoEditorRotateTab]];
|
|
|
|
[self setNeedsLayout];
|
|
|
|
if (animated)
|
|
{
|
|
_buttonsWrapperView.alpha = 0.0f;
|
|
[UIView animateWithDuration:0.15 animations:^
|
|
{
|
|
_buttonsWrapperView.alpha = 1.0f;
|
|
transitionView.alpha = 0.0f;
|
|
} completion:^(__unused BOOL finished)
|
|
{
|
|
[transitionView removeFromSuperview];
|
|
}];
|
|
}
|
|
}
|
|
|
|
- (CGRect)cancelButtonFrame
|
|
{
|
|
return _cancelButton.frame;
|
|
}
|
|
|
|
- (void)cancelButtonPressed
|
|
{
|
|
if (self.cancelPressed != nil)
|
|
self.cancelPressed();
|
|
}
|
|
|
|
- (void)doneButtonPressed
|
|
{
|
|
if (self.donePressed != nil)
|
|
self.donePressed();
|
|
}
|
|
|
|
- (void)doneButtonLongPressed:(UILongPressGestureRecognizer *)gestureRecognizer
|
|
{
|
|
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
|
|
{
|
|
if (self.doneLongPressed != nil)
|
|
self.doneLongPressed(_doneButton);
|
|
}
|
|
}
|
|
|
|
- (void)tabButtonPressed:(TGPhotoEditorButton *)sender
|
|
{
|
|
if (self.tabPressed != nil)
|
|
self.tabPressed((int)sender.tag);
|
|
}
|
|
|
|
- (void)setActiveTab:(TGPhotoEditorTab)tab
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
[button setSelected:(button.tag == tab) animated:false];
|
|
}
|
|
|
|
- (void)setDoneButtonEnabled:(bool)enabled animated:(bool)animated
|
|
{
|
|
_doneButton.userInteractionEnabled = enabled;
|
|
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_doneButton.alpha = enabled ? 1.0f : 0.2f;
|
|
} completion:nil];
|
|
}
|
|
else
|
|
{
|
|
_doneButton.alpha = enabled ? 1.0f : 0.2f;
|
|
}
|
|
}
|
|
|
|
- (void)setEditButtonsEnabled:(bool)enabled animated:(bool)animated
|
|
{
|
|
_buttonsWrapperView.userInteractionEnabled = enabled;
|
|
|
|
if (animated)
|
|
{
|
|
[UIView animateWithDuration:0.2f delay:0.0f options:UIViewAnimationOptionBeginFromCurrentState animations:^
|
|
{
|
|
_buttonsWrapperView.alpha = enabled ? 1.0f : 0.2f;
|
|
} completion:nil];
|
|
}
|
|
else
|
|
{
|
|
_buttonsWrapperView.alpha = enabled ? 1.0f : 0.2f;
|
|
}
|
|
}
|
|
|
|
- (void)setEditButtonsHidden:(bool)hidden animated:(bool)animated
|
|
{
|
|
CGFloat targetAlpha = hidden ? 0.0f : 1.0f;
|
|
|
|
if (animated)
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
button.hidden = false;
|
|
|
|
[UIView animateWithDuration:0.2f
|
|
animations:^
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
button.alpha = targetAlpha;
|
|
} completion:^(__unused BOOL finished)
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
button.hidden = hidden;
|
|
}];
|
|
}
|
|
else
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
{
|
|
button.alpha = (float)targetAlpha;
|
|
button.hidden = hidden;
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)setEditButtonsHighlighted:(TGPhotoEditorTab)buttons
|
|
{
|
|
for (TGPhotoEditorButton *button in _buttonsWrapperView.subviews)
|
|
button.active = (buttons & button.tag);
|
|
}
|
|
|
|
- (void)layoutSubviews
|
|
{
|
|
_backgroundView.frame = self.bounds;
|
|
_buttonsWrapperView.frame = _backgroundView.bounds;
|
|
|
|
NSArray *buttons = _buttonsWrapperView.subviews;
|
|
|
|
if (self.frame.size.width > self.frame.size.height)
|
|
{
|
|
if (buttons.count == 1)
|
|
{
|
|
UIView *button = buttons.firstObject;
|
|
button.frame = CGRectMake(CGFloor(self.frame.size.width / 2 - button.frame.size.width / 2), (self.frame.size.height - button.frame.size.height) / 2, button.frame.size.width, button.frame.size.height);
|
|
}
|
|
else if (buttons.count == 2)
|
|
{
|
|
UIView *leftButton = buttons.firstObject;
|
|
UIView *rightButton = buttons.lastObject;
|
|
|
|
leftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 5 * 2 - 5 - leftButton.frame.size.width / 2), (self.frame.size.height - leftButton.frame.size.height) / 2, leftButton.frame.size.width, leftButton.frame.size.height);
|
|
rightButton.frame = CGRectMake(CGCeil(self.frame.size.width - leftButton.frame.origin.x - rightButton.frame.size.width), (self.frame.size.height - rightButton.frame.size.height) / 2, rightButton.frame.size.width, rightButton.frame.size.height);
|
|
}
|
|
else if (buttons.count == 3)
|
|
{
|
|
UIView *leftButton = buttons.firstObject;
|
|
UIView *centerButton = [buttons objectAtIndex:1];
|
|
UIView *rightButton = buttons.lastObject;
|
|
|
|
centerButton.frame = CGRectMake(CGFloor(self.frame.size.width / 2 - centerButton.frame.size.width / 2), (self.frame.size.height - centerButton.frame.size.height) / 2, centerButton.frame.size.width, centerButton.frame.size.height);
|
|
|
|
leftButton.frame = CGRectMake(CGFloor(self.frame.size.width / 6 * 2 - 5 - leftButton.frame.size.width / 2), (self.frame.size.height - leftButton.frame.size.height) / 2, leftButton.frame.size.width, leftButton.frame.size.height);
|
|
|
|
rightButton.frame = CGRectMake(CGCeil(self.frame.size.width - leftButton.frame.origin.x - rightButton.frame.size.width), (self.frame.size.height - rightButton.frame.size.height) / 2, rightButton.frame.size.width, rightButton.frame.size.height);
|
|
}
|
|
|
|
_cancelButton.titleLabel.font = TGSystemFontOfSize(17);
|
|
_cancelButton.contentEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
|
|
[_cancelButton sizeToFit];
|
|
_cancelButton.frame = CGRectMake(0, 0, MAX(60.0f, CGCeil(_cancelButton.frame.size.width)), 44);
|
|
_cancelButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
|
|
|
|
_doneButton.titleLabel.font = TGMediumSystemFontOfSize(17);
|
|
_doneButton.contentEdgeInsets = UIEdgeInsetsMake(0, 27, 0, 10);
|
|
[_doneButton sizeToFit];
|
|
CGFloat doneButtonWidth = MAX(40, CGCeil(_doneButton.frame.size.width));
|
|
_doneButton.frame = CGRectMake(self.frame.size.width - doneButtonWidth, 0, doneButtonWidth, 44);
|
|
_doneButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentRight;
|
|
}
|
|
else
|
|
{
|
|
if (buttons.count == 1)
|
|
{
|
|
UIView *button = buttons.firstObject;
|
|
button.frame = CGRectMake((self.frame.size.width - button.frame.size.width) / 2, CGFloor((self.frame.size.height - button.frame.size.height) / 2), button.frame.size.width, button.frame.size.height);
|
|
}
|
|
else if (buttons.count == 2)
|
|
{
|
|
UIView *topButton = buttons.firstObject;
|
|
UIView *bottomButton = buttons.lastObject;
|
|
|
|
topButton.frame = CGRectMake((self.frame.size.width - topButton.frame.size.width) / 2, CGFloor(self.frame.size.height / 5 * 2 - 10 - topButton.frame.size.height / 2), topButton.frame.size.width, topButton.frame.size.height);
|
|
bottomButton.frame = CGRectMake((self.frame.size.width - bottomButton.frame.size.width) / 2, CGCeil(self.frame.size.height - topButton.frame.origin.y - bottomButton.frame.size.height), bottomButton.frame.size.width, bottomButton.frame.size.height);
|
|
}
|
|
else if (buttons.count == 3)
|
|
{
|
|
UIView *topButton = buttons.firstObject;
|
|
UIView *centerButton = [buttons objectAtIndex:1];
|
|
UIView *bottomButton = buttons.lastObject;
|
|
|
|
topButton.frame = CGRectMake((self.frame.size.width - topButton.frame.size.width) / 2, CGFloor(self.frame.size.height / 6 * 2 - 10 - topButton.frame.size.height / 2), topButton.frame.size.width, topButton.frame.size.height);
|
|
centerButton.frame = CGRectMake((self.frame.size.width - centerButton.frame.size.width) / 2, CGFloor((self.frame.size.height - centerButton.frame.size.height) / 2), centerButton.frame.size.width, centerButton.frame.size.height);
|
|
bottomButton.frame = CGRectMake((self.frame.size.width - bottomButton.frame.size.width) / 2, CGCeil(self.frame.size.height - topButton.frame.origin.y - bottomButton.frame.size.height), bottomButton.frame.size.width, bottomButton.frame.size.height);
|
|
}
|
|
|
|
_cancelButton.titleLabel.font = TGSystemFontOfSize(13);
|
|
_cancelButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
|
|
[_cancelButton sizeToFit];
|
|
_cancelButton.frame = CGRectMake(0, self.frame.size.height - 44, self.frame.size.width, 44);
|
|
_cancelButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
|
|
|
|
_doneButton.titleLabel.font = TGMediumSystemFontOfSize(13);
|
|
_doneButton.contentEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0);
|
|
[_doneButton sizeToFit];
|
|
_doneButton.frame = CGRectMake(0, 0, self.frame.size.width, 44);
|
|
_doneButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
|
|
}
|
|
}
|
|
|
|
- (void)transitionInAnimated:(bool)animated
|
|
{
|
|
[self transitionInAnimated:animated transparent:false];
|
|
}
|
|
|
|
- (void)transitionInAnimated:(bool)animated transparent:(bool)transparent
|
|
{
|
|
self.backgroundColor = transparent ? [UIColor clearColor] : [UIColor blackColor];
|
|
|
|
void (^animationBlock)(void) = ^
|
|
{
|
|
if (self.frame.size.width > self.frame.size.height)
|
|
{
|
|
_backgroundView.frame = CGRectMake(_backgroundView.frame.origin.x,
|
|
0,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
_backgroundView.frame = CGRectMake(0,
|
|
_backgroundView.frame.origin.y,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
};
|
|
|
|
void (^completionBlock)(BOOL) = ^(BOOL finished)
|
|
{
|
|
if (finished)
|
|
self.backgroundColor = [UIColor clearColor];
|
|
};
|
|
|
|
if (animated)
|
|
{
|
|
if (self.frame.size.width > self.frame.size.height)
|
|
{
|
|
_backgroundView.frame = CGRectMake(_backgroundView.frame.origin.x,
|
|
_backgroundView.frame.size.height,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
if (_interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
|
|
{
|
|
_backgroundView.frame = CGRectMake(-_backgroundView.frame.size.width,
|
|
_backgroundView.frame.origin.y,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
_backgroundView.frame = CGRectMake(_backgroundView.frame.size.width,
|
|
_backgroundView.frame.origin.y,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
}
|
|
|
|
if (iosMajorVersion() >= 7)
|
|
[UIView animateWithDuration:0.4f delay:0.0f usingSpringWithDamping:1.0f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveLinear animations:animationBlock completion:completionBlock];
|
|
else
|
|
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:animationBlock completion:completionBlock];
|
|
}
|
|
else
|
|
{
|
|
animationBlock();
|
|
completionBlock(true);
|
|
}
|
|
}
|
|
|
|
- (void)transitionOutAnimated:(bool)animated
|
|
{
|
|
[self transitionOutAnimated:animated transparent:false hideOnCompletion:false];
|
|
}
|
|
|
|
- (void)transitionOutAnimated:(bool)animated transparent:(bool)transparent hideOnCompletion:(bool)hideOnCompletion
|
|
{
|
|
void (^animationBlock)(void) = ^
|
|
{
|
|
if (self.frame.size.width > self.frame.size.height)
|
|
{
|
|
_backgroundView.frame = CGRectMake(_backgroundView.frame.origin.x,
|
|
_backgroundView.frame.size.height,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
if (_interfaceOrientation == UIInterfaceOrientationLandscapeLeft)
|
|
{
|
|
_backgroundView.frame = CGRectMake(-_backgroundView.frame.size.width,
|
|
_backgroundView.frame.origin.y,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
else
|
|
{
|
|
_backgroundView.frame = CGRectMake(_backgroundView.frame.size.width,
|
|
_backgroundView.frame.origin.y,
|
|
_backgroundView.frame.size.width,
|
|
_backgroundView.frame.size.height);
|
|
}
|
|
}
|
|
};
|
|
|
|
void (^completionBlock)(BOOL) = ^(__unused BOOL finished)
|
|
{
|
|
if (hideOnCompletion)
|
|
self.hidden = true;
|
|
};
|
|
|
|
self.backgroundColor = transparent ? [UIColor clearColor] : [UIColor blackColor];
|
|
|
|
if (animated)
|
|
{
|
|
if (iosMajorVersion() >= 7)
|
|
[UIView animateWithDuration:0.4f delay:0.0f usingSpringWithDamping:1.0f initialSpringVelocity:0.0f options:UIViewAnimationOptionCurveLinear animations:animationBlock completion:completionBlock];
|
|
else
|
|
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionAllowUserInteraction animations:animationBlock completion:completionBlock];
|
|
}
|
|
else
|
|
{
|
|
animationBlock();
|
|
completionBlock(true);
|
|
}
|
|
}
|
|
|
|
- (void)calculateLandscapeSizeForPossibleButtonTitles:(NSArray *)possibleButtonTitles
|
|
{
|
|
CGFloat maxWidth = 0.0f;
|
|
|
|
for (NSString *title in possibleButtonTitles)
|
|
{
|
|
CGFloat width = 0.0f;
|
|
if ([title respondsToSelector:@selector(sizeWithAttributes:)])
|
|
width = CGCeil([title sizeWithAttributes:@{ NSFontAttributeName:TGSystemFontOfSize(17) }].width - 1);
|
|
else
|
|
width = CGCeil([title sizeWithFont:TGSystemFontOfSize(17)].width - 1);
|
|
|
|
if (width > maxWidth)
|
|
maxWidth = width;
|
|
}
|
|
|
|
_landscapeSize = maxWidth;
|
|
}
|
|
|
|
- (CGFloat)landscapeSize
|
|
{
|
|
if (_landscapeSize < FLT_EPSILON)
|
|
{
|
|
[self calculateLandscapeSizeForPossibleButtonTitles:@[ [_cancelButton titleForState:UIControlStateNormal], [_doneButton titleForState:UIControlStateNormal] ]];
|
|
}
|
|
|
|
return _landscapeSize;
|
|
}
|
|
|
|
@end
|