Skip to content
This repository has been archived by the owner on Aug 14, 2019. It is now read-only.

Commit

Permalink
follow up from PR #535
Browse files Browse the repository at this point in the history
  • Loading branch information
jessesquires committed Oct 10, 2014
1 parent a03344b commit 65a691a
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 54 deletions.
7 changes: 3 additions & 4 deletions JSQMessagesDemo/DemoModelData.m
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,10 @@ - (instancetype)init
* Be sure to create your bubble images one time and reuse them for good performance.
*
*/
JSQMessagesBubbleImageFactory *factory = [[JSQMessagesBubbleImageFactory alloc] init];
self.outgoingBubbleImageData = [factory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];

self.incomingBubbleImageData = [factory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
JSQMessagesBubbleImageFactory *bubbleFactory = [[JSQMessagesBubbleImageFactory alloc] init];

self.outgoingBubbleImageData = [bubbleFactory outgoingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleLightGrayColor]];
self.incomingBubbleImageData = [bubbleFactory incomingMessagesBubbleImageWithColor:[UIColor jsq_messageBubbleGreenColor]];
}

return self;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@


@interface JSQMessagesBubbleImageFactoryTests : XCTestCase

@property (strong, nonatomic) JSQMessagesBubbleImageFactory *factory;

@end


Expand All @@ -22,10 +25,12 @@ @implementation JSQMessagesBubbleImageFactoryTests
- (void)setUp
{
[super setUp];
self.factory = [[JSQMessagesBubbleImageFactory alloc] init];
}

- (void)tearDown
{
self.factory = nil;
[super tearDown];
}

Expand All @@ -37,8 +42,7 @@ - (void)testOutgoingMessageBubbleImageView
CGPoint center = CGPointMake(bubble.size.width / 2.0f, bubble.size.height / 2.0f);
UIEdgeInsets capInsets = UIEdgeInsetsMake(center.y, center.x, center.y, center.x);

JSQMessagesBubbleImageFactory *factory = [[JSQMessagesBubbleImageFactory alloc] init];
JSQMessagesBubbleImage *bubbleImage = [factory outgoingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
JSQMessagesBubbleImage *bubbleImage = [self.factory outgoingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");

XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
Expand All @@ -63,9 +67,7 @@ - (void)testIncomingMessageBubbleImageView
CGPoint center = CGPointMake(bubble.size.width / 2.0f, bubble.size.height / 2.0f);
UIEdgeInsets capInsets = UIEdgeInsetsMake(center.y, center.x, center.y, center.x);


JSQMessagesBubbleImageFactory *factory = [[JSQMessagesBubbleImageFactory alloc] init];
JSQMessagesBubbleImage *bubbleImage = [factory incomingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
JSQMessagesBubbleImage *bubbleImage = [self.factory incomingMessagesBubbleImageWithColor:[UIColor lightGrayColor]];
XCTAssertNotNil(bubbleImage, @"Bubble image should not be nil");

XCTAssertNotNil(bubbleImage.messageBubbleImage, "Image should not be nil");
Expand All @@ -82,7 +84,6 @@ - (void)testIncomingMessageBubbleImageView
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}


- (void)testCustomOutgoingMessageBubbleImageView
{
UIImage *bubble = [UIImage imageNamed:@"clip"];
Expand All @@ -106,7 +107,6 @@ - (void)testCustomOutgoingMessageBubbleImageView
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}


- (void)testCustomIncomingMessageBubbleImageView
{
UIImage *bubble = [UIImage imageNamed:@"clip"];
Expand All @@ -130,6 +130,4 @@ - (void)testCustomIncomingMessageBubbleImageView
XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(bubbleImage.messageBubbleHighlightedImage.capInsets, capInsets), @"HighlightedImage capInsets should be equal to capInsets");
}



@end
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,35 @@

#import "JSQMessagesBubbleImage.h"


/**
* `JSQMessagesBubbleImageFactory` is a factory that provides a means for creating and styling
* `JSQMessagesBubbleImage` objects to be displayed in a `JSQMessagesCollectionViewCell` of a `JSQMessagesCollectionView`.
*/
@interface JSQMessagesBubbleImageFactory : NSObject

/**
* Creates an instance of JSQMessagesBubbleImageFactory with the default images.
* Creates and returns a new instance of `JSQMessagesBubbleImageFactory` that uses the
* default bubble image assets and cap insets.
*
* @return An initialized `JSQMessagesBubbleImageFactory` object if created successfully, `nil` otherwise.
*/
- (instancetype)init;

/**
* Creates an instance of JSQMessagesBubbleImageFactory.
* Creates and returns a new instance of `JSQMessagesBubbleImageFactory` having the specified
* bubbleImage and capInsets. These values are used internally in the factory to produce
* `JSQMessagesBubbleImage` objects.
*
* @param image A template image for all bubble images generated by this factory. The image should represent the outgoing shape, and will be flipped horizontally to make the incoming shape. This value must not be `nil`.
* @param bubbleImage A template bubble image from which all images will be generated.
* The image should represent the *outgoing* message bubble image, which will be flipped
* horizontally for generating the corresponding *incoming* message bubble images. This value must not be `nil`.
*
* @param capInsets The UIEdgeInsets which define the unstretchable regions of the image.
* @param capInsets The values to use for the cap insets that define the unstretchable regions of the image.
* Specify `UIEdgeInsetsZero` to have the factory create insets that allow the image to stretch from its center point.
*
* @return An initialized `JSQMessagesBubbleImageFactory` object if created successfully, `nil` otherwise.
*/
- (instancetype)initWithBubbleImage:(UIImage *)image capInsets:(UIEdgeInsets)capInsets;

- (instancetype)initWithBubbleImage:(UIImage *)bubbleImage capInsets:(UIEdgeInsets)capInsets;

/**
* Creates and returns a `JSQMessagesBubbleImage` object with the specified color for *outgoing* message image bubbles.
Expand Down
80 changes: 48 additions & 32 deletions JSQMessagesViewController/Factories/JSQMessagesBubbleImageFactory.m
Original file line number Diff line number Diff line change
Expand Up @@ -24,84 +24,100 @@

@interface JSQMessagesBubbleImageFactory ()

@property (nonatomic, readwrite, strong) UIImage *bubbleImage;
@property (nonatomic, readwrite, assign) UIEdgeInsets capInsets;
@property (strong, nonatomic, readonly) UIImage *bubbleImage;
@property (assign, nonatomic, readonly) UIEdgeInsets capInsets;

- (JSQMessagesBubbleImage *)messagesBubbleImageWithColor:(UIColor *)color flippedForIncoming:(BOOL)flippedForIncoming;
- (UIEdgeInsets)jsq_centerPointEdgeInsetsForImageSize:(CGSize)bubbleImageSize;

+ (UIImage *)jsq_horizontallyFlippedImageFromImage:(UIImage *)image;
- (JSQMessagesBubbleImage *)jsq_messagesBubbleImageWithColor:(UIColor *)color flippedForIncoming:(BOOL)flippedForIncoming;

+ (UIImage *)jsq_stretchableImageFromImage:(UIImage *)image withCapInsets:(UIEdgeInsets)capInsets;
- (UIImage *)jsq_horizontallyFlippedImageFromImage:(UIImage *)image;

- (UIImage *)jsq_stretchableImageFromImage:(UIImage *)image withCapInsets:(UIEdgeInsets)capInsets;

@end



@implementation JSQMessagesBubbleImageFactory

@synthesize bubbleImage;
@synthesize capInsets;

#pragma mark - Initialization

#pragma mark - Public

- (instancetype)initWithBubbleImage:(UIImage *)image capInsets:(UIEdgeInsets)insets {
NSParameterAssert(image != nil);
- (instancetype)initWithBubbleImage:(UIImage *)bubbleImage capInsets:(UIEdgeInsets)capInsets
{
NSParameterAssert(bubbleImage != nil);
self = [super init];
if (self) {
self.bubbleImage = image;
self.capInsets = insets;
_bubbleImage = bubbleImage;

if (UIEdgeInsetsEqualToEdgeInsets(capInsets, UIEdgeInsetsZero)) {
_capInsets = [self jsq_centerPointEdgeInsetsForImageSize:bubbleImage.size];
}
else {
_capInsets = capInsets;
}
}
return self;
}

- (instancetype)init {
UIImage *bubble = [UIImage imageNamed:@"bubble_min"];
NSAssert(bubble != nil, @"Unable to load default image in %s. Please make sure default resources are included in your project.",
__PRETTY_FUNCTION__);
CGPoint center = CGPointMake(bubble.size.width / 2.0f, bubble.size.height / 2.0f);
UIEdgeInsets insets = UIEdgeInsetsMake(center.y, center.x, center.y, center.x);
return [self initWithBubbleImage:bubble capInsets:insets];
- (instancetype)init
{
return [self initWithBubbleImage:[UIImage jsq_bubbleCompactImage] capInsets:UIEdgeInsetsZero];
}

- (void)dealloc
{
_bubbleImage = nil;
}

#pragma mark - Public

- (JSQMessagesBubbleImage *)outgoingMessagesBubbleImageWithColor:(UIColor *)color
{
NSParameterAssert(color != nil);
return [self messagesBubbleImageWithColor:color flippedForIncoming:NO];
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:NO];
}

- (JSQMessagesBubbleImage *)incomingMessagesBubbleImageWithColor:(UIColor *)color
{
NSParameterAssert(color != nil);
return [self messagesBubbleImageWithColor:color flippedForIncoming:YES];
return [self jsq_messagesBubbleImageWithColor:color flippedForIncoming:YES];
}

#pragma mark - Private

- (JSQMessagesBubbleImage *)messagesBubbleImageWithColor:(UIColor *)color flippedForIncoming:(BOOL)flippedForIncoming
- (UIEdgeInsets)jsq_centerPointEdgeInsetsForImageSize:(CGSize)bubbleImageSize
{
// make image stretchable from center point
CGPoint center = CGPointMake(bubbleImageSize.width / 2.0f, bubbleImageSize.height / 2.0f);
return UIEdgeInsetsMake(center.y, center.x, center.y, center.x);
}

- (JSQMessagesBubbleImage *)jsq_messagesBubbleImageWithColor:(UIColor *)color flippedForIncoming:(BOOL)flippedForIncoming
{
NSParameterAssert(color != nil);

UIImage *normalBubble = [self.bubbleImage jsq_imageMaskedWithColor:color];
UIImage *highlightedBubble = [self.bubbleImage jsq_imageMaskedWithColor:[color jsq_colorByDarkeningColorWithValue:0.12f]];

if (flippedForIncoming) {
normalBubble = [JSQMessagesBubbleImageFactory jsq_horizontallyFlippedImageFromImage:normalBubble];
highlightedBubble = [JSQMessagesBubbleImageFactory jsq_horizontallyFlippedImageFromImage:highlightedBubble];
normalBubble = [self jsq_horizontallyFlippedImageFromImage:normalBubble];
highlightedBubble = [self jsq_horizontallyFlippedImageFromImage:highlightedBubble];
}

normalBubble = [JSQMessagesBubbleImageFactory jsq_stretchableImageFromImage:normalBubble withCapInsets:self.capInsets];
highlightedBubble = [JSQMessagesBubbleImageFactory jsq_stretchableImageFromImage:highlightedBubble withCapInsets:self.capInsets];
normalBubble = [self jsq_stretchableImageFromImage:normalBubble withCapInsets:self.capInsets];
highlightedBubble = [self jsq_stretchableImageFromImage:highlightedBubble withCapInsets:self.capInsets];

return [[JSQMessagesBubbleImage alloc] initWithMessageBubbleImage:normalBubble highlightedImage:highlightedBubble];
}

+ (UIImage *)jsq_horizontallyFlippedImageFromImage:(UIImage *)image
- (UIImage *)jsq_horizontallyFlippedImageFromImage:(UIImage *)image
{
return [UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:UIImageOrientationUpMirrored];
}

+ (UIImage *)jsq_stretchableImageFromImage:(UIImage *)image withCapInsets:(UIEdgeInsets)capInsets
- (UIImage *)jsq_stretchableImageFromImage:(UIImage *)image withCapInsets:(UIEdgeInsets)capInsets
{
return [image resizableImageWithCapInsets:capInsets resizingMode:UIImageResizingModeStretch];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,9 @@ - (void)configureWithEllipsisColor:(UIColor *)ellipsisColor

CGFloat bubbleMarginMinimumSpacing = 6.0f;
CGFloat indicatorMarginMinimumSpacing = 26.0f;

JSQMessagesBubbleImageFactory *bubbleImageFactory = [[JSQMessagesBubbleImageFactory alloc] init];

JSQMessagesBubbleImageFactory *bubbleImageFactory = [[JSQMessagesBubbleImageFactory alloc] init];

if (shouldDisplayOnLeft) {
self.bubbleImageView.image = [bubbleImageFactory incomingMessagesBubbleImageWithColor:messageBubbleColor].messageBubbleImage;

Expand Down

0 comments on commit 65a691a

Please sign in to comment.