1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-03 09:57:46 +01:00
Telegram/Telegraph/TGCameraFlashControl.m
2015-10-01 19:19:52 +03:00

612 lines
24 KiB
Objective-C

#import "TGCameraFlashControl.h"
#import "UIControl+HitTestEdgeInsets.h"
#import "TGCameraInterfaceAssets.h"
#import "TGModernButton.h"
const CGFloat TGCameraFlashControlHeight = 44.0f;
@interface TGCameraFlashControl ()
{
UIButton *_flashIconView;
UIButton *_autoButton;
UIButton *_onButton;
UIButton *_offButton;
bool _active;
}
@end
@implementation TGCameraFlashControl
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
self.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10);
_flashIconView = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 34, 44)];
_flashIconView.adjustsImageWhenHighlighted = false;
_flashIconView.contentMode = UIViewContentModeCenter;
_flashIconView.exclusiveTouch = true;
_flashIconView.hitTestEdgeInsets = UIEdgeInsetsMake(0, -10, 0, -10);
_flashIconView.tag = -1;
[_flashIconView setImage:[UIImage imageNamed:@"CameraFlashButton"] forState:UIControlStateNormal];
[_flashIconView addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_flashIconView];
static UIImage *highlightedIconImage = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^
{
UIImage *image = [UIImage imageNamed:@"CameraFlashButton"];
UIGraphicsBeginImageContextWithOptions(image.size, false, 0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
CGContextSetBlendMode (context, kCGBlendModeSourceAtop);
CGContextSetFillColorWithColor(context, [TGCameraInterfaceAssets accentColor].CGColor);
CGContextFillRect(context, CGRectMake(0, 0, image.size.width, image.size.height));
highlightedIconImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
});
[_flashIconView setImage:highlightedIconImage forState:UIControlStateSelected];
[_flashIconView setImage:highlightedIconImage forState:UIControlStateHighlighted | UIControlStateSelected];
_autoButton = [[UIButton alloc] init];
_autoButton.backgroundColor = [UIColor clearColor];
_autoButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
_autoButton.exclusiveTouch = true;
_autoButton.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -15, -10, -15);
_autoButton.tag = PGCameraFlashModeAuto;
_autoButton.titleLabel.font = [TGCameraInterfaceAssets normalFontOfSize:13];
[_autoButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashAuto") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets normalColor], NSKernAttributeName: @2 }] forState:UIControlStateNormal];
[_autoButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashAuto") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets accentColor], NSKernAttributeName: @2 }] forState:UIControlStateSelected];
[_autoButton setAttributedTitle:[_autoButton attributedTitleForState:UIControlStateSelected] forState:UIControlStateHighlighted | UIControlStateSelected];
[_autoButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[_autoButton sizeToFit];
_autoButton.frame = (CGRect){ CGPointZero, [TGCameraFlashControl _sizeForModeButtonWithTitle:[_autoButton attributedTitleForState:UIControlStateNormal]] };
[self addSubview:_autoButton];
_onButton = [[UIButton alloc] init];
_onButton.backgroundColor = [UIColor clearColor];
_onButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
_onButton.exclusiveTouch = true;
_onButton.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -15, -10, -15);
_onButton.tag = PGCameraFlashModeOn;
_onButton.titleLabel.font = [TGCameraInterfaceAssets normalFontOfSize:13];
[_onButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashOn") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets normalColor], NSKernAttributeName: @2 }] forState:UIControlStateNormal];
[_onButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashOn") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets accentColor], NSKernAttributeName: @2 }] forState:UIControlStateSelected];
[_onButton setAttributedTitle:[_onButton attributedTitleForState:UIControlStateSelected] forState:UIControlStateHighlighted | UIControlStateSelected];
[_onButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[_onButton sizeToFit];
_onButton.frame = (CGRect){ CGPointZero, [TGCameraFlashControl _sizeForModeButtonWithTitle:[_onButton attributedTitleForState:UIControlStateNormal]] };
[self addSubview:_onButton];
_offButton = [[UIButton alloc] init];
_offButton.backgroundColor = [UIColor clearColor];
_offButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
_offButton.exclusiveTouch = true;
_offButton.hitTestEdgeInsets = UIEdgeInsetsMake(-10, -15, -10, -15);
_offButton.tag = PGCameraFlashModeOff;
_offButton.titleLabel.font = [TGCameraInterfaceAssets normalFontOfSize:13];
[_offButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashOff") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets normalColor], NSKernAttributeName: @2 }] forState:UIControlStateNormal];
[_offButton setAttributedTitle:[[NSAttributedString alloc] initWithString:TGLocalized(@"Camera.FlashOff") attributes:@{ NSForegroundColorAttributeName: [TGCameraInterfaceAssets accentColor], NSKernAttributeName: @2 }] forState:UIControlStateSelected];
[_offButton setAttributedTitle:[_offButton attributedTitleForState:UIControlStateSelected] forState:UIControlStateHighlighted | UIControlStateSelected];
[_offButton addTarget:self action:@selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[_offButton sizeToFit];
_offButton.frame = (CGRect){ CGPointZero, [TGCameraFlashControl _sizeForModeButtonWithTitle:[_offButton attributedTitleForState:UIControlStateNormal]] };
[self addSubview:_offButton];
[UIView performWithoutAnimation:^
{
self.mode = PGCameraFlashModeOff;
[self setActive:false animated:false];
}];
}
return self;
}
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView *view = [super hitTest:point withEvent:event];
if ([view isKindOfClass:[UIButton class]])
return view;
return nil;
}
- (void)buttonPressed:(UIButton *)sender
{
if (!_active)
{
[self setActive:true animated:true];
}
else
{
if (sender != _flashIconView)
self.mode = (int)sender.tag;
else
self.mode = _mode;
if (self.modeChanged != nil)
self.modeChanged(self.mode);
}
}
- (void)setFlashUnavailable:(bool)unavailable
{
self.userInteractionEnabled = !unavailable;
[self setActive:false animated:false];
}
- (void)setActive:(bool)active animated:(bool)animated
{
_active = active;
if (animated)
{
self.userInteractionEnabled = false;
if (active)
{
UIView *animatedView = nil;
UIView *snapshotView = nil;
CGRect targetFrame = CGRectZero;
if (self.mode != PGCameraFlashModeAuto)
{
_autoButton.frame = [self _autoButtonFrameForInterfaceOrientation:_interfaceOrientation];
_autoButton.alpha = 0.0f;
_autoButton.hidden = false;
}
else
{
animatedView = _autoButton;
targetFrame = [self _autoButtonFrameForInterfaceOrientation:_interfaceOrientation];
snapshotView = [animatedView snapshotViewAfterScreenUpdates:false];
}
_autoButton.selected = (self.mode == PGCameraFlashModeAuto);
if (self.mode != PGCameraFlashModeOn)
{
_onButton.frame = [self _onButtonFrameForInterfaceOrientation:_interfaceOrientation];
_onButton.alpha = 0.0f;
_onButton.hidden = false;
}
else
{
animatedView = _onButton;
targetFrame = [self _onButtonFrameForInterfaceOrientation:_interfaceOrientation];
}
_onButton.selected = (self.mode == PGCameraFlashModeOn);
if (self.mode != PGCameraFlashModeOff)
{
_offButton.frame = [self _offButtonFrameForInterfaceOrientation:_interfaceOrientation];
_offButton.alpha = 0.0f;
_offButton.hidden = false;
}
else
{
animatedView = _offButton;
targetFrame = [self _offButtonFrameForInterfaceOrientation:_interfaceOrientation];
snapshotView = [animatedView snapshotViewAfterScreenUpdates:false];
}
_offButton.selected = (self.mode == PGCameraFlashModeOff);
if (snapshotView != nil)
{
snapshotView.frame = animatedView.frame;
[animatedView.superview insertSubview:snapshotView belowSubview:animatedView];
animatedView.alpha = 0.0f;
}
UIView *iconSnapshotView = nil;
if (_flashIconView.selected)
{
iconSnapshotView = [_flashIconView snapshotViewAfterScreenUpdates:false];
iconSnapshotView.frame = _flashIconView.frame;
[_flashIconView.superview insertSubview:iconSnapshotView belowSubview:_flashIconView];
_flashIconView.selected = false;
_flashIconView.alpha = 0.0f;
}
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^
{
_flashIconView.alpha = 1.0f;
_flashIconView.frame = [self _flashIconFrameForActive:active interfaceOrientation:_interfaceOrientation];
iconSnapshotView.frame = _flashIconView.frame;
_autoButton.alpha = 1.0f;
_onButton.alpha = 1.0f;
_offButton.alpha = 1.0f;
animatedView.alpha = 1.0f;
animatedView.frame = targetFrame;
snapshotView.frame = targetFrame;
} completion:^(BOOL finished)
{
[snapshotView removeFromSuperview];
[iconSnapshotView removeFromSuperview];
if (finished)
self.userInteractionEnabled = true;
}];
}
else
{
UIView *animatedView = nil;
UIView *snapshotView = nil;
UIView *iconSnapshotView = nil;
switch (self.mode)
{
case PGCameraFlashModeAuto:
{
animatedView = _autoButton;
snapshotView = [animatedView snapshotViewAfterScreenUpdates:false];
_autoButton.selected = false;
}
break;
case PGCameraFlashModeOn:
{
animatedView = _onButton;
if (!_onButton.selected)
{
snapshotView = [animatedView snapshotViewAfterScreenUpdates:false];
_onButton.selected = true;
}
iconSnapshotView = [_flashIconView snapshotViewAfterScreenUpdates:false];
iconSnapshotView.frame = _flashIconView.frame;
[_flashIconView.superview insertSubview:iconSnapshotView belowSubview:_flashIconView];
_flashIconView.selected = true;
_flashIconView.alpha = 0.0f;
}
break;
case PGCameraFlashModeOff:
{
animatedView = _offButton;
snapshotView = [animatedView snapshotViewAfterScreenUpdates:false];
_offButton.selected = false;
}
break;
default:
break;
}
if (snapshotView != nil)
{
snapshotView.frame = animatedView.frame;
[animatedView.superview insertSubview:snapshotView belowSubview:animatedView];
animatedView.alpha = 0.0f;
}
[UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^
{
_flashIconView.alpha = 1.0f;
_flashIconView.frame = [self _flashIconFrameForActive:active interfaceOrientation:_interfaceOrientation];
iconSnapshotView.frame = _flashIconView.frame;
if (self.mode != PGCameraFlashModeAuto)
_autoButton.alpha = 0.0f;
if (self.mode != PGCameraFlashModeOn)
_onButton.alpha = 0.0f;
if (self.mode != PGCameraFlashModeOff)
_offButton.alpha = 0.0f;
animatedView.alpha = 1.0f;
animatedView.frame = [self _selectedButtonFrameForSize:animatedView.frame.size interfaceOrientation:_interfaceOrientation];
snapshotView.frame = animatedView.frame;
} completion:^(BOOL finished)
{
[snapshotView removeFromSuperview];
[iconSnapshotView removeFromSuperview];
if (finished)
{
self.userInteractionEnabled = true;
if (self.mode != PGCameraFlashModeAuto)
_autoButton.hidden = true;
if (self.mode != PGCameraFlashModeOn)
_onButton.hidden = true;
if (self.mode != PGCameraFlashModeOff)
_offButton.hidden = true;
}
}];
}
}
else
{
_flashIconView.frame = [self _flashIconFrameForActive:active interfaceOrientation:_interfaceOrientation];
if (active)
{
_flashIconView.selected = false;
_autoButton.frame = [self _autoButtonFrameForInterfaceOrientation:_interfaceOrientation];
_autoButton.alpha = 1.0f;
_autoButton.hidden = false;
_autoButton.selected = (self.mode == PGCameraFlashModeAuto);
_onButton.frame = [self _onButtonFrameForInterfaceOrientation:_interfaceOrientation];
_onButton.alpha = 1.0f;
_onButton.hidden = false;
_onButton.selected = (self.mode == PGCameraFlashModeOn);
_offButton.frame = [self _offButtonFrameForInterfaceOrientation:_interfaceOrientation];
_offButton.alpha = 1.0f;
_offButton.hidden = false;
_offButton.selected = (self.mode == PGCameraFlashModeOff);
}
else
{
switch (self.mode)
{
case PGCameraFlashModeOff:
{
_flashIconView.selected = false;
_autoButton.alpha = 0.0f;
_autoButton.hidden = true;
_autoButton.selected = false;
_onButton.alpha = 0.0f;
_onButton.hidden = true;
_onButton.selected = false;
_offButton.frame = [self _selectedButtonFrameForSize:_offButton.frame.size interfaceOrientation:_interfaceOrientation];
_offButton.alpha = 1.0f;
_offButton.hidden = false;
_offButton.selected = false;
}
break;
case PGCameraFlashModeOn:
{
_flashIconView.selected = true;
_autoButton.alpha = 0.0f;
_autoButton.hidden = true;
_autoButton.selected = false;
_onButton.frame = [self _selectedButtonFrameForSize:_onButton.frame.size interfaceOrientation:_interfaceOrientation];
_onButton.alpha = 1.0f;
_onButton.hidden = false;
_onButton.selected = true;
_offButton.alpha = 0.0f;
_offButton.hidden = true;
_offButton.selected = false;
}
break;
case PGCameraFlashModeAuto:
{
_flashIconView.selected = false;
_autoButton.frame = [self _selectedButtonFrameForSize:_autoButton.frame.size interfaceOrientation:_interfaceOrientation];
_autoButton.alpha = 1.0f;
_autoButton.hidden = false;
_autoButton.selected = false;
_onButton.alpha = 0.0f;
_onButton.hidden = true;
_onButton.selected = false;
_offButton.alpha = 0.0f;
_offButton.hidden = true;
_offButton.selected = false;
}
break;
default:
break;
}
}
}
if (active && self.becameActive != nil)
self.becameActive();
}
- (void)setMode:(PGCameraFlashMode)mode
{
_mode = mode;
[self setActive:false animated:_active];
}
- (void)dismissAnimated:(bool)animated
{
if (animated && _active)
[self setActive:false animated:animated];
else
[self setActive:false animated:false];
}
- (void)setHidden:(BOOL)hidden
{
self.alpha = hidden ? 0.0f : 1.0f;
super.hidden = hidden;
[self setActive:false animated:false];
}
- (void)setHidden:(bool)hidden animated:(bool)animated
{
if (animated)
{
super.hidden = false;
self.userInteractionEnabled = false;
[UIView animateWithDuration:0.25f
animations:^
{
self.alpha = hidden ? 0.0f : 1.0f;
} completion:^(BOOL finished)
{
self.userInteractionEnabled = true;
if (finished)
self.hidden = hidden;
[self setActive:false animated:false];
}];
}
else
{
self.alpha = hidden ? 0.0f : 1.0f;
super.hidden = hidden;
[self setActive:false animated:false];
}
}
- (void)setInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
_interfaceOrientation = interfaceOrientation;
[self setActive:false animated:false];
}
- (CGRect)_flashIconFrameForActive:(bool)active interfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGPoint origin = CGPointZero;
CGSize size = self.frame.size;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
size = CGSizeMake(size.height, size.width);
switch (interfaceOrientation)
{
case UIInterfaceOrientationLandscapeLeft:
{
if (active)
origin = CGPointMake(size.width - _flashIconView.frame.size.width - 5, (size.height - _flashIconView.frame.size.height) / 2);
else
origin = CGPointMake(size.width - _flashIconView.frame.size.width - 5, (size.height - _flashIconView.frame.size.height) / 2 - 9);
}
break;
case UIInterfaceOrientationLandscapeRight:
{
if (active)
origin = CGPointMake(5, (size.height - _flashIconView.frame.size.height) / 2);
else
origin = CGPointMake(5, (size.height - _flashIconView.frame.size.height) / 2 - 9);
}
break;
case UIInterfaceOrientationPortraitUpsideDown:
{
if (active)
{
origin = CGPointMake(0, 0);
}
else
{
CGFloat maxWidth = MAX(MAX(_offButton.frame.size.width, _onButton.frame.size.width), _autoButton.frame.size.width);
origin = CGPointMake(size.width - _flashIconView.frame.size.width - maxWidth, 0);
}
}
break;
default:
{
origin = CGPointZero;
}
break;
}
return CGRectMake(origin.x, origin.y, _flashIconView.frame.size.width, _flashIconView.frame.size.height);
}
- (CGRect)_selectedButtonFrameForSize:(CGSize)buttonSize interfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGPoint origin = CGPointZero;
CGSize size = self.frame.size;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
size = CGSizeMake(size.height, size.width);
switch (interfaceOrientation)
{
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
{
origin = CGPointMake(CGRectGetMidX(_flashIconView.frame) - buttonSize.width / 2, 21);
}
break;
case UIInterfaceOrientationPortraitUpsideDown:
{
CGRect iconFrame = [self _flashIconFrameForActive:false interfaceOrientation:interfaceOrientation];
origin = CGPointMake(iconFrame.origin.x + iconFrame.size.width - 3, (size.height - buttonSize.height) / 2);
}
break;
default:
{
origin = CGPointMake(_flashIconView.frame.size.width - 5,
(size.height - buttonSize.height) / 2);
}
break;
}
return CGRectMake(origin.x, origin.y, buttonSize.width, buttonSize.height);
}
- (CGRect)_autoButtonFrameForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGSize size = self.frame.size;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
size = CGSizeMake(size.height, size.width);
return CGRectMake(size.width / 4 - _autoButton.frame.size.width / 2,
(size.height - _autoButton.frame.size.height) / 2,
_autoButton.frame.size.width, _autoButton.frame.size.height);
}
- (CGRect)_onButtonFrameForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGSize size = self.frame.size;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
size = CGSizeMake(size.height, size.width);
return CGRectMake((size.width - _onButton.frame.size.width) / 2,
(size.height - _onButton.frame.size.height) / 2,
_onButton.frame.size.width, _onButton.frame.size.height);
}
- (CGRect)_offButtonFrameForInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
CGSize size = self.frame.size;
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
size = CGSizeMake(size.height, size.width);
return CGRectMake(size.width / 4 * 3 - _offButton.frame.size.width / 2,
(size.height - _offButton.frame.size.height) / 2,
_offButton.frame.size.width, _offButton.frame.size.height);
}
+ (CGSize)_sizeForModeButtonWithTitle:(NSAttributedString *)title
{
CGSize size = title.size;
CGFloat width = CGCeil(size.width);
if (iosMajorVersion() < 7)
width += 2;
return CGSizeMake(width, 20);
}
@end