Issue 479
[zxing.git] / iphone / ZXingWidget / Classes / OverlayView.m
1 /**
2  * Copyright 2009 Jeff Verkoeyen
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #import "OverlayView.h"
18
19 static const CGFloat kPadding = 10;
20
21 @interface OverlayView()
22 @property (nonatomic,assign) UIButton *cancelButton;
23 @end
24
25
26 @implementation OverlayView
27
28 @synthesize delegate, oneDMode;
29 @synthesize points = _points;
30 @synthesize cancelButton;
31 @synthesize cropRect;
32
33 ////////////////////////////////////////////////////////////////////////////////////////////////////
34 - (id) initWithFrame:(CGRect)theFrame cancelEnabled:(BOOL)isCancelEnabled oneDMode:(BOOL)isOneDModeEnabled {
35   if( self = [super initWithFrame:theFrame] ) {
36
37     CGFloat rectSize = self.frame.size.width - kPadding * 2;
38     if (!oneDMode) {
39       cropRect = CGRectMake(kPadding, (self.frame.size.height - rectSize) / 2, rectSize, rectSize);
40     } else {
41       CGFloat rectSize2 = self.frame.size.height - kPadding * 2;
42       cropRect = CGRectMake(kPadding, kPadding, rectSize, rectSize2);           
43     }
44
45     self.backgroundColor = [UIColor clearColor];
46     self.oneDMode = isOneDModeEnabled;
47     if (isCancelEnabled) {
48       UIButton *butt = [UIButton buttonWithType:UIButtonTypeRoundedRect]; 
49       self.cancelButton = butt;
50       [cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];
51       if (oneDMode) {
52         [cancelButton setTransform:CGAffineTransformMakeRotation(M_PI/2)];
53         [cancelButton setFrame:CGRectMake(20, 175, 45, 130)];
54       }
55       else {
56         [cancelButton setFrame:CGRectMake(95, 420, 130, 45)];                   
57       }
58       
59       [cancelButton addTarget:self action:@selector(cancel:) forControlEvents:UIControlEventTouchUpInside];
60       [self addSubview:cancelButton];
61       [self addSubview:imageView];
62     }
63   }
64   return self;
65 }
66
67 - (void)cancel:(id)sender {
68         // call delegate to cancel this scanner
69         if (delegate != nil) {
70                 [delegate cancelled];
71         }
72 }
73
74 ////////////////////////////////////////////////////////////////////////////////////////////////////
75 - (void) dealloc {
76         [imageView release];
77         [_points release];
78         [super dealloc];
79 }
80
81
82 - (void)drawRect:(CGRect)rect inContext:(CGContextRef)context {
83         CGContextBeginPath(context);
84         CGContextMoveToPoint(context, rect.origin.x, rect.origin.y);
85         CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y);
86         CGContextAddLineToPoint(context, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height);
87         CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y + rect.size.height);
88         CGContextAddLineToPoint(context, rect.origin.x, rect.origin.y);
89         CGContextStrokePath(context);
90 }
91
92 - (CGPoint)map:(CGPoint)point {
93     CGPoint center;
94     center.x = cropRect.size.width/2;
95     center.y = cropRect.size.height/2;
96     float x = point.x - center.x;
97     float y = point.y - center.y;
98     int rotation = 90;
99     switch(rotation) {
100     case 0:
101         point.x = x;
102         point.y = y;
103         break;
104     case 90:
105         point.x = -y;
106         point.y = x;
107         break;
108     case 180:
109         point.x = -x;
110         point.y = -y;
111         break;
112     case 270:
113         point.x = y;
114         point.y = -x;
115         break;
116     }
117     point.x = point.x + center.x;
118     point.y = point.y + center.y;
119     return point;
120 }
121
122 ////////////////////////////////////////////////////////////////////////////////////////////////////
123 - (void)drawRect:(CGRect)rect {
124         [super drawRect:rect];
125         CGContextRef c = UIGraphicsGetCurrentContext();
126   
127         if (nil != _points) {
128     //          [imageView.image drawAtPoint:cropRect.origin];
129         }
130         
131         CGFloat white[4] = {1.0f, 1.0f, 1.0f, 1.0f};
132         CGContextSetStrokeColor(c, white);
133         CGContextSetFillColor(c, white);
134         [self drawRect:cropRect inContext:c];
135         
136   //    CGContextSetStrokeColor(c, white);
137         //      CGContextSetStrokeColor(c, white);
138         CGContextSaveGState(c);
139         if (oneDMode) {
140                 char *text = "Place a red line over the bar code to be scanned.";
141                 CGContextSelectFont(c, "Helvetica", 15, kCGEncodingMacRoman);
142                 CGContextScaleCTM(c, -1.0, 1.0);
143                 CGContextRotateCTM(c, M_PI/2);
144                 CGContextShowTextAtPoint(c, 74.0, 285.0, text, 49);
145         }
146         else {
147                 char *text = "Place a barcode inside the";
148                 char *text2 = "viewfinder rectangle to scan it.";
149                 CGContextSelectFont(c, "Helvetica", 18, kCGEncodingMacRoman);
150                 CGContextScaleCTM(c, -1.0, 1.0);
151                 CGContextRotateCTM(c, M_PI);
152                 CGContextShowTextAtPoint(c, 48.0, -45.0, text, 26);
153                 CGContextShowTextAtPoint(c, 33.0, -70.0, text2, 32);
154         }
155         CGContextRestoreGState(c);
156         int offset = rect.size.width / 2;
157         if (oneDMode) {
158                 CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
159                 CGContextSetStrokeColor(c, red);
160                 CGContextSetFillColor(c, red);
161                 CGContextBeginPath(c);
162                 //              CGContextMoveToPoint(c, rect.origin.x + kPadding, rect.origin.y + offset);
163                 //              CGContextAddLineToPoint(c, rect.origin.x + rect.size.width - kPadding, rect.origin.y + offset);
164                 CGContextMoveToPoint(c, rect.origin.x + offset, rect.origin.y + kPadding);
165                 CGContextAddLineToPoint(c, rect.origin.x + offset, rect.origin.y + rect.size.height - kPadding);
166                 CGContextStrokePath(c);
167         }
168         if( nil != _points ) {
169                 CGFloat blue[4] = {0.0f, 1.0f, 0.0f, 1.0f};
170                 CGContextSetStrokeColor(c, blue);
171                 CGContextSetFillColor(c, blue);
172                 if (oneDMode) {
173                         CGPoint val1 = [self map:[[_points objectAtIndex:0] CGPointValue]];
174                         CGPoint val2 = [self map:[[_points objectAtIndex:1] CGPointValue]];
175                         CGContextMoveToPoint(c, offset, val1.x);
176                         CGContextAddLineToPoint(c, offset, val2.x);
177                         CGContextStrokePath(c);
178                 }
179                 else {
180                         CGRect smallSquare = CGRectMake(0, 0, 10, 10);
181                         for( NSValue* value in _points ) {
182                                 CGPoint point = [self map:[value CGPointValue]];
183                                 smallSquare.origin = CGPointMake(
184                                          cropRect.origin.x + point.x - smallSquare.size.width / 2,
185                                          cropRect.origin.y + point.y - smallSquare.size.height / 2);
186                                 [self drawRect:smallSquare inContext:c];
187                         }
188                 }
189         }
190 }
191
192
193 ////////////////////////////////////////////////////////////////////////////////////////////////////
194 /*
195  - (void) setImage:(UIImage*)image {
196  //if( nil == imageView ) {
197 // imageView = [[UIImageView alloc] initWithImage:image];
198 // imageView.alpha = 0.5;
199 // } else {
200  imageView.image = image;
201  //}
202  
203  //CGRect frame = imageView.frame;
204  //frame.origin.x = self.cropRect.origin.x;
205  //frame.origin.y = self.cropRect.origin.y;
206  //imageView.frame = CGRectMake(0,0, 30, 50);
207  
208  //[_points release];
209  //_points = nil;
210  //self.backgroundColor = [UIColor clearColor];
211  
212  //[self setNeedsDisplay];
213  }
214  */
215
216 ////////////////////////////////////////////////////////////////////////////////////////////////////
217 - (UIImage*) image {
218         return imageView.image;
219 }
220
221
222 ////////////////////////////////////////////////////////////////////////////////////////////////////
223 - (void) setPoints:(NSMutableArray*)pnts {
224     [pnts retain];
225     [_points release];
226     _points = pnts;
227         
228     if (pnts != nil) {
229         self.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.25];
230     }
231     [self setNeedsDisplay];
232 }
233
234 - (void) setPoint:(CGPoint)point {
235     if (!_points) {
236         _points = [[NSMutableArray alloc] init];
237     }
238     if (_points.count > 3) {
239         [_points removeObjectAtIndex:0];
240     }
241     [_points addObject:[NSValue valueWithCGPoint:point]];
242     [self setNeedsDisplay];
243 }
244
245
246 @end