You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-ios/Signal/src/ViewControllers/ConversationView/Cells/OWSBubbleView.m

195 lines
4.7 KiB
Matlab

7 years ago
//
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
//
#import "OWSBubbleView.h"
#import "OWSBubbleShapeView.h"
7 years ago
#import <SignalMessaging/UIView+OWS.h>
NS_ASSUME_NONNULL_BEGIN
const CGFloat kOWSMessageCellCornerRadius_Large = 18;
const CGFloat kOWSMessageCellCornerRadius_Small = 4;
7 years ago
7 years ago
@interface OWSBubbleView ()
@property (nonatomic) CAShapeLayer *maskLayer;
@property (nonatomic) CAShapeLayer *shapeLayer;
@property (nonatomic, readonly) NSMutableArray<id<OWSBubbleViewPartner>> *partnerViews;
7 years ago
@end
#pragma mark -
7 years ago
@implementation OWSBubbleView
7 years ago
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
self.layoutMargins = UIEdgeInsetsZero;
7 years ago
self.shapeLayer = [CAShapeLayer new];
[self.layer addSublayer:self.shapeLayer];
self.maskLayer = [CAShapeLayer new];
self.layer.mask = self.maskLayer;
_partnerViews = [NSMutableArray new];
7 years ago
return self;
}
7 years ago
- (void)setFrame:(CGRect)frame
{
7 years ago
// We only need to update our layers if the _size_ of this view
// changes since the contents of the layers are in local coordinates.
BOOL didChangeSize = !CGSizeEqualToSize(self.frame.size, frame.size);
7 years ago
[super setFrame:frame];
if (didChangeSize) {
7 years ago
[self updateLayers];
7 years ago
}
7 years ago
7 years ago
// We always need to inform the "bubble stroke view" (if any) if our
// frame/bounds/center changes. Its contents are not in local coordinates.
[self updatePartnerViews];
7 years ago
}
- (void)setBounds:(CGRect)bounds
{
7 years ago
// We only need to update our layers if the _size_ of this view
// changes since the contents of the layers are in local coordinates.
BOOL didChangeSize = !CGSizeEqualToSize(self.bounds.size, bounds.size);
7 years ago
[super setBounds:bounds];
if (didChangeSize) {
7 years ago
[self updateLayers];
7 years ago
}
7 years ago
7 years ago
// We always need to inform the "bubble stroke view" (if any) if our
// frame/bounds/center changes. Its contents are not in local coordinates.
[self updatePartnerViews];
7 years ago
}
- (void)setCenter:(CGPoint)center
{
[super setCenter:center];
7 years ago
// We always need to inform the "bubble stroke view" (if any) if our
// frame/bounds/center changes. Its contents are not in local coordinates.
[self updatePartnerViews];
7 years ago
}
- (void)setBubbleColor:(nullable UIColor *)bubbleColor
{
_bubbleColor = bubbleColor;
[self updateLayers];
// Prevent the shape layer from animating changes.
[CATransaction begin];
7 years ago
[CATransaction setDisableActions:YES];
7 years ago
self.shapeLayer.fillColor = bubbleColor.CGColor;
[CATransaction commit];
7 years ago
}
7 years ago
- (void)setSharpCorners:(UIRectCorner)sharpCorners
{
7 years ago
_sharpCorners = sharpCorners;
[self updateLayers];
}
7 years ago
- (void)updateLayers
7 years ago
{
if (!self.maskLayer) {
return;
}
if (!self.shapeLayer) {
return;
}
7 years ago
7 years ago
UIBezierPath *bezierPath = [self maskPath];
7 years ago
// Prevent the shape layer from animating changes.
[CATransaction begin];
7 years ago
[CATransaction setDisableActions:YES];
7 years ago
self.shapeLayer.fillColor = self.bubbleColor.CGColor;
self.shapeLayer.path = bezierPath.CGPath;
self.maskLayer.path = bezierPath.CGPath;
[CATransaction commit];
7 years ago
}
7 years ago
- (UIBezierPath *)maskPath
{
7 years ago
return [self.class maskPathForSize:self.bounds.size sharpCorners:self.sharpCorners];
7 years ago
}
7 years ago
+ (UIBezierPath *)maskPathForSize:(CGSize)size sharpCorners:(UIRectCorner)sharpCorners
7 years ago
{
CGRect bounds = CGRectZero;
bounds.size = size;
UIBezierPath *bezierPath = [UIBezierPath new];
CGFloat bubbleTop = 0.f;
CGFloat bubbleLeft = 0.f;
CGFloat bubbleBottom = size.height;
CGFloat bubbleRight = size.width;
7 years ago
return [OWSBubbleShapeView roundedBezierRectWithBubbleTop:bubbleTop
bubbleLeft:bubbleLeft
bubbleBottom:bubbleBottom
bubbleRight:bubbleRight
sharpCornerRadius:kOWSMessageCellCornerRadius_Small
wideCornerRadius:kOWSMessageCellCornerRadius_Large
sharpCorners:sharpCorners];
7 years ago
}
#pragma mark - Coordination
- (void)addPartnerView:(id<OWSBubbleViewPartner>)partnerView
{
OWSAssert(self.partnerViews);
[partnerView setBubbleView:self];
[self.partnerViews addObject:partnerView];
}
- (void)clearPartnerViews
{
OWSAssert(self.partnerViews);
[self.partnerViews removeAllObjects];
}
- (void)updatePartnerViews
{
[self layoutIfNeeded];
for (id<OWSBubbleViewPartner> partnerView in self.partnerViews) {
[partnerView updateLayers];
}
}
- (CGFloat)minWidth
{
7 years ago
return (kOWSMessageCellCornerRadius_Large * 2);
}
7 years ago
@end
NS_ASSUME_NONNULL_END