Skip to content

Commit

Permalink
Merge pull request #3 from luugiathuy/master
Browse files Browse the repository at this point in the history
Multiple slotlights support
  • Loading branch information
mcconkiee committed Jul 26, 2012
2 parents b15b0aa + a81fc3c commit cd55d33
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 86 deletions.
10 changes: 5 additions & 5 deletions HintMakerExample/EMHint.h
Expand Up @@ -31,9 +31,9 @@ typedef enum


/*
// return a view where the spotlight should shine
// return an array of UIView where spotlights should shine
*/
-(UIView*)hintStateViewToHint:(id)hintState;
-(NSArray*)hintStateViewsToHint:(id)hintState;

/*
// the default hint space is a label with white helvetica text dynamically centered,
Expand All @@ -42,10 +42,10 @@ typedef enum
-(UIView*)hintStateViewForDialog:(id)hintState;

/*
// return a rect for where the spotlight should shine.
// convenient if a UIView is not an option
// return an array of rects (NSValue objs) for where spotlights should shine.
// convenient if UIView array is not an option
*/
-(CGRect)hintStateRectToHint:(id)hintState;
-(NSArray*)hintStateRectsToHint:(id)hintState;

/*
// return NO, if you plan to daisy chain hints, or do someother action
Expand Down
22 changes: 11 additions & 11 deletions HintMakerExample/EMHint.m
Expand Up @@ -69,23 +69,23 @@ -(void)presentModalMessage:(NSString*)message where:(UIView*)presentationPlace
{
//incase we have many in a row
if(_modalView!=nil)
[_modalView removeFromSuperview];
[self clear];

if ([self.hintDelegate respondsToSelector:@selector(hintStateViewToHint:)]) {
UIView *v = [self.hintDelegate hintStateViewToHint:self];
if(v!=nil)
_modalView = [[EMHintsView alloc] initWithFrame:presentationPlace.frame forView:v];
if ([self.hintDelegate respondsToSelector:@selector(hintStateViewsToHint:)]) {
NSArray *viewArray = [self.hintDelegate hintStateViewsToHint:self];
if(viewArray!=nil)
_modalView = [[EMHintsView alloc] initWithFrame:presentationPlace.frame forViews:viewArray];
}

if ([self.hintDelegate respondsToSelector:@selector(hintStateRectToHint:)]) {
CGRect rect = [self.hintDelegate hintStateRectToHint:self];
if (rect.size.width>0 && rect.size.height>0)
_modalView = [[EMHintsView alloc] initWithFrame:presentationPlace.frame withRect:rect];
if ([self.hintDelegate respondsToSelector:@selector(hintStateRectsToHint:)]) {
NSArray* rectArray = [self.hintDelegate hintStateRectsToHint:self];
if (rectArray != nil)
_modalView = [[EMHintsView alloc] initWithFrame:presentationPlace.frame withRects:rectArray];
}

if (_modalView==nil)
[NSException raise:@"No ModalView protocols"
format:@"you must at least implement a view or point "];
_modalView = [[EMHintsView alloc] initWithFrame:presentationPlace.frame];

[_modalView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[presentationPlace addSubview:_modalView];

Expand Down
12 changes: 8 additions & 4 deletions HintMakerExample/EMHintsView.h
Expand Up @@ -17,9 +17,13 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI

@interface EMHintsView : UIView
{
CGPoint _position;
CGFloat _radius;
// array positions of spotlights
NSMutableArray* _positionArray;
// array radius of spotlights
NSMutableArray* _radiusArray;
}
- (id)initWithFrame:(CGRect)frame forView:(UIView*)onView;
- (id)initWithFrame:(CGRect)frame withRect:(CGRect)aRect;

- (id)initWithFrame:(CGRect)frame;
- (id)initWithFrame:(CGRect)frame forViews:(NSArray*)viewArray;
- (id)initWithFrame:(CGRect)frame withRects:(NSArray*)rectArray;
@end
145 changes: 92 additions & 53 deletions HintMakerExample/EMHintsView.m
Expand Up @@ -20,46 +20,75 @@

@implementation EMHintsView

- (id)initWithFrame:(CGRect)frame withRect:(CGRect)aRect
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_position = CGPointMake(aRect.origin.x,
aRect.origin.y);
_radius = aRect.size.width;
// initialize arrays
_positionArray = [[NSMutableArray alloc] init];
_radiusArray = [[NSMutableArray alloc] init];

// set background color
[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:BACKGROUND_ALPHA]];
}
return self;
}

- (id)initWithFrame:(CGRect)frame forView:(UIView*)onView
- (id)initWithFrame:(CGRect)frame withRects:(NSArray *)rectArray
{
self = [super initWithFrame:frame];
if (self) {
_positionArray = [[NSMutableArray alloc] init];
_radiusArray = [[NSMutableArray alloc] init];
// add spotlight position and radius
for (NSValue* theRectObj in rectArray)
{
CGRect theRect = [theRectObj CGRectValue];
CGPoint pos = CGPointMake(theRect.origin.x, theRect.origin.y);
CGFloat radius = theRect.size.width;
[_positionArray addObject:[NSValue valueWithCGPoint:pos]];
[_radiusArray addObject:[NSNumber numberWithFloat:radius]];
}
[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:BACKGROUND_ALPHA]];
}
return self;
}

- (id)initWithFrame:(CGRect)frame forViews:(NSArray *)viewArray
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_position = CGPointMake(onView.frame.origin.x + (onView.frame.size.width/2)
, onView.frame.origin.y + (onView.frame.size.height/2) );
_radius = onView.frame.size.width;
_positionArray = [[NSMutableArray alloc] init];
_radiusArray = [[NSMutableArray alloc] init];
// add spotlight position and radius
for (UIView* theView in viewArray)
{
CGPoint pos = CGPointMake(theView.frame.origin.x + (theView.frame.size.width/2)
, theView.frame.origin.y + (theView.frame.size.height/2) );
CGFloat radius = theView.frame.size.width;
[_positionArray addObject:[NSValue valueWithCGPoint:pos]];
[_radiusArray addObject:[NSNumber numberWithFloat:radius]];
}

[self setBackgroundColor:[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:BACKGROUND_ALPHA]];
}
return self;
}

-(void)_background:(CGRect)rect
{
CGPoint c = _position;

// context for drawing
CGContextRef context = UIGraphicsGetCurrentContext();

CGImageRef backgroundimage = CGBitmapContextCreateImage(context);
CGContextClearRect(context, rect);
//CGContextDrawImage(context, rect, backgroundimage);

// Draw the masking image
// save state
CGContextSaveGState(context);

//flip the context (right-sideup)
// flip the context (right-sideup)
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

Expand All @@ -76,47 +105,57 @@ -(void)_background:(CGRect)rect

CGFloat colorLocations[2] = {0.25,0.5};

//create the gradient Ref
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorspace, components, colorLocations, 2);
CGColorSpaceRelease(colorspace);

//draw the shape
CGFloat radius =_radius;
CGMutablePathRef path = CGPathCreateMutable();
//
//draw a rect around view
CGPathAddRect(path, NULL, CGRectMake(c.x - _radius, c.y -radius,100,100));
CGPathAddLineToPoint(path, NULL, c.x +_radius, c.y - _radius);
CGPathAddLineToPoint(path, NULL, c.x +_radius, c.y + _radius);
CGPathAddLineToPoint(path, NULL, c.x - _radius, c.y + _radius);
CGPathAddLineToPoint(path, NULL, c.x - _radius, c.y);
CGPathAddLineToPoint(path, NULL, c.x, c.y);
/*
//draw a rectangle like spotlight --- i'll get to this later
CGPathMoveToPoint(path, NULL, c.x-radius, c.y-radius);
CGPathAddLineToPoint(path, NULL, c.x, c.y-radius);
CGPathAddArcToPoint(path, NULL, c.x+radius, c.y-radius, c.x+radius, c.y, radius);
CGPathAddArcToPoint(path, NULL, c.x+radius, c.y +radius, c.x , c.y+radius, radius);
CGPathAddArcToPoint(path, NULL, c.x -radius, c.y + radius, c.x-radius, c.y, radius);
CGPathAddArcToPoint(path, NULL, c.x-radius, c.y - radius, c.x, c.y-radius, radius);
CGContextAddPath(context, path);
CGContextClip(context);
//fill with gradient
CGContextDrawRadialGradient(context, gradientRef, c, 0.0f, c, _radius*2, 0);
*/


CGContextAddPath(context, path);
CGPathRelease(path);
CGContextClip(context);
// draw spotlights
int spotlightCount = _positionArray.count;
for (int i=0; i<spotlightCount; ++i)
{
// center and radius of spotlight
CGPoint c = [[_positionArray objectAtIndex:i] CGPointValue];
CGFloat radius = [[_radiusArray objectAtIndex:i] floatValue];

//draw the shape
CGMutablePathRef path = CGPathCreateMutable();
//
//draw a rect around view
CGPathAddRect(path, NULL, CGRectMake(c.x - radius, c.y -radius,100,100));
CGPathAddLineToPoint(path, NULL, c.x + radius, c.y - radius);
CGPathAddLineToPoint(path, NULL, c.x + radius, c.y + radius);
CGPathAddLineToPoint(path, NULL, c.x - radius, c.y + radius);
CGPathAddLineToPoint(path, NULL, c.x - radius, c.y);
CGPathAddLineToPoint(path, NULL, c.x, c.y);
/*
//draw a rectangle like spotlight --- i'll get to this later
CGPathMoveToPoint(path, NULL, c.x-radius, c.y-radius);
CGPathAddLineToPoint(path, NULL, c.x, c.y-radius);
CGPathAddArcToPoint(path, NULL, c.x+radius, c.y-radius, c.x+radius, c.y, radius);
CGPathAddArcToPoint(path, NULL, c.x+radius, c.y +radius, c.x , c.y+radius, radius);
CGPathAddArcToPoint(path, NULL, c.x -radius, c.y + radius, c.x-radius, c.y, radius);
CGPathAddArcToPoint(path, NULL, c.x-radius, c.y - radius, c.x, c.y-radius, radius);
CGContextAddPath(context, path);
CGContextClip(context);
//fill with gradient
CGContextDrawRadialGradient(context, gradientRef, c, 0.0f, c, _radius*2, 0);
*/
CGContextSaveGState(context);

CGContextAddPath(context, path);
CGPathRelease(path);
CGContextClip(context);

//add gradient
//create the gradient Ref
CGGradientRef gradientRef = CGGradientCreateWithColorComponents(colorspace, components, colorLocations, 2);
CGContextDrawRadialGradient(context, gradientRef, c, 0.0f, c, radius*2, 0);
CGGradientRelease(gradientRef);

CGContextRestoreGState(context);
}

//add gradient
CGContextDrawRadialGradient(context, gradientRef, c, 0.0f, c, _radius*2, 0);
CGGradientRelease(gradientRef);
CGColorSpaceRelease(colorspace);
CGContextRestoreGState(context);

//convert drawing to image for masking
Expand Down
4 changes: 2 additions & 2 deletions HintMakerExample/EMViewController.m
Expand Up @@ -19,9 +19,9 @@ @implementation EMViewController
#pragma mark ---------------------------------->>
#pragma mark -------------->>hint deleage

-(UIView*)hintStateViewToHint:(id)hintState
-(NSArray*)hintStateViewsToHint:(id)hintState
{
return _info;
return [[NSArray alloc] initWithObjects:_info, nil];
}
-(UIView*)hintStateViewForDialog:(id)hintState
{
Expand Down
1 change: 1 addition & 0 deletions HintMakerExample/HintHelper.h
Expand Up @@ -24,6 +24,7 @@ typedef enum
EMHintDialogTypeButton,
EMHintDialogTypeList,
EMHintDialogTypeBack,
EMHintDialogTypeListAndBack,
EMHintDialogTypeCount
}EMHintDialogType;

Expand Down
38 changes: 28 additions & 10 deletions HintMakerExample/HintHelper.m
Expand Up @@ -30,6 +30,9 @@ -(void)doNext
case EMHintDialogTypeList:
[modalState presentModalMessage:@"This is a list button! \r\nProtocol: returned rect" where:_vc.navigationController.view];
break;
case EMHintDialogTypeListAndBack:
[modalState presentModalMessage:@"Multiple spotlights: list and back button \r\nProtocol: returned rect" where:_vc.navigationController.view];
break;
default:
[modalState presentModalMessage:@"" where:_vc.navigationController.view];
break;
Expand Down Expand Up @@ -62,31 +65,46 @@ -(void)hintStateDidClose:(id)hintState



-(CGRect)hintStateRectToHint:(id)hintState
-(NSArray*)hintStateRectsToHint:(id)hintState
{
CGFloat ht = 50.0;
CGFloat statusBarHt = 20.0;
CGRect rect;
NSArray* rectArray = nil;
switch (_curType) {
case EMHintDialogTypeInfo:
rect = CGRectMake(_vc.view.frame.size.width/2 ,
_vc.view.frame.size.height/2 + (statusBarHt + 44),
ht,ht);
{
CGRect rect = CGRectMake(_vc.view.frame.size.width/2 ,
_vc.view.frame.size.height/2 + (statusBarHt + 44),
ht,ht);
rectArray = [[NSArray alloc] initWithObjects:[NSValue valueWithCGRect:rect], nil];
}
break;
case EMHintDialogTypeList:
rect = CGRectMake(290, ht/2 + statusBarHt,ht,ht);
{
CGRect rect = CGRectMake(290, ht/2 + statusBarHt,ht,ht);
rectArray = [[NSArray alloc] initWithObjects:[NSValue valueWithCGRect:rect], nil];
}
break;
case EMHintDialogTypeBack:
rect= CGRectMake(25, ht/2 + statusBarHt,ht,ht);
{
CGRect rect= CGRectMake(25, ht/2 + statusBarHt,ht,ht);
rectArray = [[NSArray alloc] initWithObjects:[NSValue valueWithCGRect:rect], nil];
}
break;
case EMHintDialogTypeListAndBack:
{
CGRect backRect = CGRectMake(25, ht/2 + statusBarHt,ht,ht);
CGRect listRect = CGRectMake(290, ht/2 + statusBarHt,ht,ht);
rectArray = [[NSArray alloc] initWithObjects:[NSValue valueWithCGRect:backRect], [NSValue valueWithCGRect:listRect], nil];
}
break;

case EMHintDialogTypeButton:
rect = CGRectMake(0, 0, 1, 1);
break;
default:
rect = CGRectMake(0, 0, 1, 1);
break;
}
return rect;
return rectArray;
}


Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -2,7 +2,7 @@

## Overview

**EMHint** is an iOS class group that easily adds a spotlight-like effect to a view highlighting or hinting at something that may be important on the screen.The protocols of EMHintDelegate allow users to override many of the default actions and views. Tapping the black overlay fades it away.
**EMHint** is an iOS class group that easily adds multiple spotlight-like effects to a view highlighting or hinting at some things that may be important on the screen.The protocols of EMHintDelegate allow users to override many of the default actions and views. Tapping the black overlay fades it away.

Great for quick "how to" or tutorials in your app.

Expand Down

0 comments on commit cd55d33

Please sign in to comment.