2012-02-17 10:05:17 -08:00
// - * - Mode : ObjC ; tab - width : 2 ; indent - tabs - mode : nil ; c - basic - offset : 2 - * -
2010-05-12 11:13:27 -07:00
/ * *
* Copyright 2009 Jeff Verkoeyen
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : // www . apache . org / licenses / LICENSE -2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
# import "OverlayView.h"
static const CGFloat kPadding = 10 ;
2012-02-17 10:05:17 -08:00
static const CGFloat kLicenseButtonPadding = 10 ;
2010-05-12 11:13:27 -07:00
2010-06-15 15:01:04 -07:00
@ interface OverlayView ( )
@ property ( nonatomic , assign ) UIButton * cancelButton ;
2012-02-17 10:05:17 -08:00
@ property ( nonatomic , assign ) UIButton * licenseButton ;
2011-01-27 08:45:25 -08:00
@ property ( nonatomic , retain ) UILabel * instructionsLabel ;
2010-06-15 15:01:04 -07:00
@ end
2010-05-12 11:13:27 -07:00
@ implementation OverlayView
2010-05-18 18:52:38 -07:00
@ synthesize delegate , oneDMode ;
2010-05-12 11:13:27 -07:00
@ synthesize points = _points ;
2010-06-15 15:01:04 -07:00
@ synthesize cancelButton ;
2012-02-17 10:05:17 -08:00
@ synthesize licenseButton ;
2010-08-17 14:18:56 -07:00
@ synthesize cropRect ;
2011-01-27 08:45:25 -08:00
@ synthesize instructionsLabel ;
2011-03-16 01:11:20 -07:00
@ synthesize displayedMessage ;
2012-09-25 03:06:56 -07:00
@ synthesize cancelButtonTitle ;
@ synthesize cancelEnabled ;
2010-05-12 11:13:27 -07:00
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
2012-02-17 10:05:17 -08:00
- ( id ) initWithFrame : ( CGRect ) theFrame cancelEnabled : ( BOOL ) isCancelEnabled oneDMode : ( BOOL ) isOneDModeEnabled {
return [ self initWithFrame : theFrame cancelEnabled : isCancelEnabled oneDMode : isOneDModeEnabled showLicense : YES ] ;
}
- ( id ) initWithFrame : ( CGRect ) theFrame cancelEnabled : ( BOOL ) isCancelEnabled oneDMode : ( BOOL ) isOneDModeEnabled showLicense : ( BOOL ) showLicenseButton {
2010-12-22 09:33:00 -08:00
self = [ super initWithFrame : theFrame ] ;
if ( self ) {
2010-08-17 14:18:56 -07:00
CGFloat rectSize = self . frame . size . width - kPadding * 2 ;
if ( ! oneDMode ) {
cropRect = CGRectMake ( kPadding , ( self . frame . size . height - rectSize ) / 2 , rectSize , rectSize ) ;
} else {
CGFloat rectSize2 = self . frame . size . height - kPadding * 2 ;
cropRect = CGRectMake ( kPadding , kPadding , rectSize , rectSize2 ) ;
}
self . backgroundColor = [ UIColor clearColor ] ;
2010-06-06 05:42:31 -07:00
self . oneDMode = isOneDModeEnabled ;
2012-02-17 10:05:17 -08:00
if ( showLicenseButton ) {
self . licenseButton = [ UIButton buttonWithType : UIButtonTypeInfoLight ] ;
CGRect lbFrame = [ licenseButton frame ] ;
lbFrame . origin . x = self . frame . size . width - licenseButton . frame . size . width - kLicenseButtonPadding ;
lbFrame . origin . y = self . frame . size . height - licenseButton . frame . size . height - kLicenseButtonPadding ;
[ licenseButton setFrame : lbFrame ] ;
[ licenseButton addTarget : self action : @ selector ( showLicenseAlert : ) forControlEvents : UIControlEventTouchUpInside ] ;
[ self addSubview : licenseButton ] ;
}
2012-09-25 03:06:56 -07:00
self . cancelEnabled = isCancelEnabled ;
2012-10-13 17:29:07 -07:00
if ( self . cancelEnabled ) {
UIButton * butt = [ UIButton buttonWithType : UIButtonTypeRoundedRect ] ;
self . cancelButton = butt ;
if ( [ self . cancelButtonTitle length ] > 0 ) {
[ cancelButton setTitle : self . cancelButtonTitle forState : UIControlStateNormal ] ;
} else {
[ cancelButton setTitle : NSLocalizedStringWithDefaultValue ( @ "OverlayView cancel button title" , nil , [ NSBundle mainBundle ] , @ "Cancel" , @ "Cancel" ) forState : UIControlStateNormal ] ;
}
[ cancelButton addTarget : self action : @ selector ( cancel : ) forControlEvents : UIControlEventTouchUpInside ] ;
[ self addSubview : cancelButton ] ;
}
2010-06-06 05:42:31 -07:00
}
2010-08-17 14:18:56 -07:00
return self ;
2010-05-12 11:13:27 -07:00
}
- ( void ) cancel : ( id ) sender {
// call delegate to cancel this scanner
if ( delegate ! = nil ) {
[ delegate cancelled ] ;
}
}
2012-02-17 10:05:17 -08:00
- ( void ) showLicenseAlert : ( id ) sender {
2013-04-07 12:24:11 -07:00
NSString * title =
NSLocalizedStringWithDefaultValue ( @ "OverlayView license alert title" , nil , [ NSBundle mainBundle ] , @ "License" , @ "License" ) ;
NSString * message =
NSLocalizedStringWithDefaultValue ( @ "OverlayView license alert message" , nil , [ NSBundle mainBundle ] , @ "Scanning functionality provided by ZXing library, licensed under Apache 2.0 license." , @ "Scanning functionality provided by ZXing library, licensed under Apache 2.0 license." ) ;
NSString * cancelTitle =
NSLocalizedStringWithDefaultValue ( @ "OverlayView license alert cancel title" , nil , [ NSBundle mainBundle ] , @ "OK" , @ "OK" ) ;
NSString * viewTitle =
NSLocalizedStringWithDefaultValue ( @ "OverlayView license alert view title" , nil , [ NSBundle mainBundle ] , @ "View License" , @ "View License" ) ;
UIAlertView * av =
[ [ UIAlertView alloc ] initWithTitle : title message : message delegate : self cancelButtonTitle : cancelTitle otherButtonTitles : viewTitle , nil ] ;
2012-02-17 10:05:17 -08:00
[ av show ] ;
2013-04-07 12:24:11 -07:00
[ self retain ] ; // For the delegate callback . . .
2012-02-17 10:05:17 -08:00
[ av release ] ;
}
- ( void ) alertView : ( UIAlertView * ) alertView clickedButtonAtIndex : ( NSInteger ) buttonIndex {
2013-04-07 12:24:11 -07:00
if ( buttonIndex = = [ alertView firstOtherButtonIndex ] ) {
[ [ UIApplication sharedApplication ] openURL : [ NSURL URLWithString : @ "http://www.apache.org/licenses/LICENSE-2.0.html" ] ] ;
}
[ self release ] ;
2012-02-17 10:05:17 -08:00
}
2010-05-12 11:13:27 -07:00
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
- ( void ) dealloc {
[ _points release ] ;
2011-01-27 08:45:25 -08:00
[ instructionsLabel release ] ;
2011-03-16 01:11:20 -07:00
[ displayedMessage release ] ;
2012-09-25 03:06:56 -07:00
[ cancelButtonTitle release ] ,
2010-05-12 11:13:27 -07:00
[ super dealloc ] ;
}
- ( void ) drawRect : ( CGRect ) rect inContext : ( CGContextRef ) context {
CGContextBeginPath ( context ) ;
CGContextMoveToPoint ( context , rect . origin . x , rect . origin . y ) ;
CGContextAddLineToPoint ( context , rect . origin . x + rect . size . width , rect . origin . y ) ;
CGContextAddLineToPoint ( context , rect . origin . x + rect . size . width , rect . origin . y + rect . size . height ) ;
CGContextAddLineToPoint ( context , rect . origin . x , rect . origin . y + rect . size . height ) ;
CGContextAddLineToPoint ( context , rect . origin . x , rect . origin . y ) ;
CGContextStrokePath ( context ) ;
}
2010-08-17 14:18:56 -07:00
- ( CGPoint ) map : ( CGPoint ) point {
CGPoint center ;
center . x = cropRect . size . width / 2 ;
center . y = cropRect . size . height / 2 ;
float x = point . x - center . x ;
float y = point . y - center . y ;
int rotation = 90 ;
switch ( rotation ) {
case 0 :
point . x = x ;
point . y = y ;
break ;
case 90 :
point . x = - y ;
point . y = x ;
break ;
case 180 :
point . x = - x ;
point . y = - y ;
break ;
case 270 :
point . x = y ;
point . y = - x ;
break ;
}
point . x = point . x + center . x ;
point . y = point . y + center . y ;
return point ;
}
2010-05-12 11:13:27 -07:00
2011-03-16 01:11:20 -07:00
# define kTextMargin 10
2010-05-12 11:13:27 -07:00
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
- ( void ) drawRect : ( CGRect ) rect {
[ super drawRect : rect ] ;
2011-03-16 01:11:20 -07:00
if ( displayedMessage = = nil ) {
2012-02-17 10:05:17 -08:00
self . displayedMessage = NSLocalizedStringWithDefaultValue ( @ "OverlayView displayed message" , nil , [ NSBundle mainBundle ] , @ "Place a barcode inside the viewfinder rectangle to scan it." , @ "Place a barcode inside the viewfinder rectangle to scan it." ) ;
2011-03-16 01:11:20 -07:00
}
2010-05-12 11:13:27 -07:00
CGContextRef c = UIGraphicsGetCurrentContext ( ) ;
2010-06-06 05:42:31 -07:00
2010-05-12 11:13:27 -07:00
CGFloat white [ 4 ] = { 1.0 f , 1.0 f , 1.0 f , 1.0 f } ;
CGContextSetStrokeColor ( c , white ) ;
CGContextSetFillColor ( c , white ) ;
[ self drawRect : cropRect inContext : c ] ;
2010-06-06 05:42:31 -07:00
// CGContextSetStrokeColor ( c , white ) ;
2010-05-12 11:13:27 -07:00
// CGContextSetStrokeColor ( c , white ) ;
CGContextSaveGState ( c ) ;
2010-05-18 18:52:38 -07:00
if ( oneDMode ) {
2012-02-17 10:05:17 -08:00
NSString * text = NSLocalizedStringWithDefaultValue ( @ "OverlayView 1d instructions" , nil , [ NSBundle mainBundle ] , @ "Place a red line over the bar code to be scanned." , @ "Place a red line over the bar code to be scanned." ) ;
UIFont * helvetica15 = [ UIFont fontWithName : @ "Helvetica" size : 15 ] ;
CGSize textSize = [ text sizeWithFont : helvetica15 ] ;
2010-05-18 18:52:38 -07:00
CGContextRotateCTM ( c , M_PI / 2 ) ;
2012-02-17 10:05:17 -08:00
// Invert height and width , because we are rotated .
CGPoint textPoint = CGPointMake ( self . bounds . size . height / 2 - textSize . width / 2 , self . bounds . size . width * -1.0 f + 20.0 f ) ;
[ text drawAtPoint : textPoint withFont : helvetica15 ] ;
2010-05-18 18:52:38 -07:00
}
else {
2011-03-16 01:11:20 -07:00
UIFont * font = [ UIFont systemFontOfSize : 18 ] ;
CGSize constraint = CGSizeMake ( rect . size . width - 2 * kTextMargin , cropRect . origin . y ) ;
2011-03-16 08:57:43 -07:00
CGSize displaySize = [ self . displayedMessage sizeWithFont : font constrainedToSize : constraint ] ;
2011-03-16 01:11:20 -07:00
CGRect displayRect = CGRectMake ( ( rect . size . width - displaySize . width ) / 2 , cropRect . origin . y - displaySize . height , displaySize . width , displaySize . height ) ;
[ self . displayedMessage drawInRect : displayRect withFont : font lineBreakMode : UILineBreakModeWordWrap alignment : UITextAlignmentCenter ] ;
2010-05-18 18:52:38 -07:00
}
2010-05-12 11:13:27 -07:00
CGContextRestoreGState ( c ) ;
2010-05-18 18:52:38 -07:00
int offset = rect . size . width / 2 ;
if ( oneDMode ) {
CGFloat red [ 4 ] = { 1.0 f , 0.0 f , 0.0 f , 1.0 f } ;
CGContextSetStrokeColor ( c , red ) ;
CGContextSetFillColor ( c , red ) ;
CGContextBeginPath ( c ) ;
// CGContextMoveToPoint ( c , rect . origin . x + kPadding , rect . origin . y + offset ) ;
// CGContextAddLineToPoint ( c , rect . origin . x + rect . size . width - kPadding , rect . origin . y + offset ) ;
CGContextMoveToPoint ( c , rect . origin . x + offset , rect . origin . y + kPadding ) ;
CGContextAddLineToPoint ( c , rect . origin . x + offset , rect . origin . y + rect . size . height - kPadding ) ;
CGContextStrokePath ( c ) ;
}
2010-05-12 11:13:27 -07:00
if ( nil ! = _points ) {
CGFloat blue [ 4 ] = { 0.0 f , 1.0 f , 0.0 f , 1.0 f } ;
CGContextSetStrokeColor ( c , blue ) ;
CGContextSetFillColor ( c , blue ) ;
2010-05-18 18:52:38 -07:00
if ( oneDMode ) {
2010-08-17 14:18:56 -07:00
CGPoint val1 = [ self map : [ [ _points objectAtIndex : 0 ] CGPointValue ] ] ;
CGPoint val2 = [ self map : [ [ _points objectAtIndex : 1 ] CGPointValue ] ] ;
2010-05-18 18:52:38 -07:00
CGContextMoveToPoint ( c , offset , val1 . x ) ;
CGContextAddLineToPoint ( c , offset , val2 . x ) ;
CGContextStrokePath ( c ) ;
}
else {
CGRect smallSquare = CGRectMake ( 0 , 0 , 10 , 10 ) ;
for ( NSValue * value in _points ) {
2010-08-17 14:18:56 -07:00
CGPoint point = [ self map : [ value CGPointValue ] ] ;
2010-05-18 18:52:38 -07:00
smallSquare . origin = CGPointMake (
2010-06-06 05:42:31 -07:00
cropRect . origin . x + point . x - smallSquare . size . width / 2 ,
cropRect . origin . y + point . y - smallSquare . size . height / 2 ) ;
2010-05-18 18:52:38 -07:00
[ self drawRect : smallSquare inContext : c ] ;
}
2010-05-12 11:13:27 -07:00
}
}
}
// // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // // //
2010-08-17 14:18:56 -07:00
- ( void ) setPoints : ( NSMutableArray * ) pnts {
[ pnts retain ] ;
[ _points release ] ;
_points = pnts ;
2010-08-08 21:46:06 -07:00
2010-08-17 14:18:56 -07:00
if ( pnts ! = nil ) {
self . backgroundColor = [ UIColor colorWithWhite : 1.0 alpha : 0.25 ] ;
}
[ self setNeedsDisplay ] ;
2010-08-08 21:46:06 -07:00
}
2010-05-12 11:13:27 -07:00
2010-08-17 14:18:56 -07:00
- ( void ) setPoint : ( CGPoint ) point {
if ( ! _points ) {
_points = [ [ NSMutableArray alloc ] init ] ;
}
if ( _points . count > 3 ) {
[ _points removeObjectAtIndex : 0 ] ;
}
[ _points addObject : [ NSValue valueWithCGPoint : point ] ] ;
[ self setNeedsDisplay ] ;
2010-05-12 11:13:27 -07:00
}
2012-10-13 17:29:07 -07:00
- ( void ) layoutSubviews {
[ super layoutSubviews ] ;
if ( cancelButton ) {
if ( oneDMode ) {
[ cancelButton setTransform : CGAffineTransformMakeRotation ( M_PI / 2 ) ] ;
[ cancelButton setFrame : CGRectMake ( 20 , 175 , 45 , 130 ) ] ;
} else {
CGSize theSize = CGSizeMake ( 100 , 50 ) ;
CGRect rect = self . frame ;
CGRect theRect = CGRectMake ( ( rect . size . width - theSize . width ) / 2 , cropRect . origin . y + cropRect . size . height + 20 , theSize . width , theSize . height ) ;
[ cancelButton setFrame : theRect ] ;
}
}
}
2010-05-12 11:13:27 -07:00
@ end