2 // DecoderViewController.m
5 // Created by Christian Brunschen on 22/05/2008.
7 * Copyright 2008 ZXing authors
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
22 #import "DecoderViewController.h"
24 #import "NSString+HTML.h"
25 #import "ParsedResult.h"
26 #import "ResultAction.h"
29 #import "ArchiveController.h"
31 #import "TwoDDecoderResult.h"
34 @implementation DecoderViewController
36 @synthesize cameraBarItem;
37 @synthesize libraryBarItem;
38 @synthesize savedPhotosBarItem;
39 @synthesize archiveBarItem;
40 @synthesize actionBarItem;
42 @synthesize messageView;
43 @synthesize resultView;
44 @synthesize imageView;
51 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
52 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
53 // Initialization code
54 self.title = @"ZXing";
56 Decoder *d = [[Decoder alloc] init];
65 // Implement loadView if you want to create a view hierarchy programmatically
69 CGRect mViewFrame = self.resultView.bounds;
70 UITextView *mView = [[UITextView alloc] initWithFrame:mViewFrame];
71 mView.backgroundColor = [UIColor yellowColor];
73 mView.editable = false;
74 mView.scrollEnabled = true;
75 mView.autoresizingMask = UIViewAutoresizingFlexibleHeight |
76 UIViewAutoresizingFlexibleWidth |
77 UIViewAutoresizingFlexibleLeftMargin |
78 UIViewAutoresizingFlexibleRightMargin |
79 UIViewAutoresizingFlexibleTopMargin |
80 UIViewAutoresizingFlexibleBottomMargin;
81 self.messageView = mView;
84 [self.resultView addSubview:self.messageView];
86 [self showMessage:NSLocalizedString(@"Please take or choose a picture containing a barcode", @"")];
89 - (void) updateToolbar {
90 self.cameraBarItem.enabled = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera];
91 self.savedPhotosBarItem.enabled = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeSavedPhotosAlbum];
92 self.libraryBarItem.enabled = [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary];
93 self.archiveBarItem.enabled = true;
94 self.actionBarItem.enabled = (self.result != nil) && ([self.result actions] != nil) && ([self.result actions].count > 0);
98 // If you need to do additional setup after loading the view, override viewDidLoad.
104 - (void)pickAndDecodeFromSource:(UIImagePickerControllerSourceType) sourceType {
106 // Create the Image Picker
107 if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {
108 UIImagePickerController* picker = [[UIImagePickerController alloc] init];
109 picker.sourceType = sourceType;
110 picker.delegate = self;
111 picker.allowsImageEditing = [[NSUserDefaults standardUserDefaults]
112 boolForKey:@"allowEditing"];
114 // Picker is displayed asynchronously.
115 [self presentModalViewController:picker animated:YES];
117 NSLog(@"Attempted to pick an image with illegal source type '%d'", sourceType);
121 - (IBAction)pickAndDecode:(id) sender {
122 UIImagePickerControllerSourceType sourceType;
123 int i = [sender tag];
126 case 0: sourceType = UIImagePickerControllerSourceTypeCamera; break;
127 case 1: sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum; break;
128 case 2: sourceType = UIImagePickerControllerSourceTypePhotoLibrary; break;
129 default: sourceType = UIImagePickerControllerSourceTypeSavedPhotosAlbum;
131 [self pickAndDecodeFromSource:sourceType];
135 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
136 // Return YES for supported orientations
137 return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
141 - (void)didReceiveMemoryWarning {
142 [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
143 // Release anything that's not essential, such as cached data
150 [actionBarItem release];
151 [cameraBarItem release];
152 [libraryBarItem release];
153 [savedPhotosBarItem release];
154 [archiveBarItem release];
160 - (void)showMessage:(NSString *)message {
162 NSLog(@"Showing message '%@'", message);
164 self.messageView.text = message;
165 [self.messageView sizeToFit];
168 // DecoderDelegate methods
170 - (void)decoder:(Decoder *)decoder willDecodeImage:(UIImage *)image {
171 [self.imageView setImage:image];
172 [self showMessage:[NSString stringWithFormat:NSLocalizedString(@"Decoding image (%.0fx%.0f) ...", @"shown while image is decoding"), image.size.width, image.size.height]];
175 - (void)decoder:(Decoder *)decoder
176 decodingImage:(UIImage *)image
177 usingSubset:(UIImage *)subset
178 progress:(NSString *)message {
179 [self.imageView setImage:subset];
180 [self showMessage:message];
183 - (void)presentResultForString:(NSString *)resultString {
184 self.result = [ParsedResult parsedResultForString:resultString];
185 [self showMessage:[self.result stringForDisplay]];
186 self.actions = self.result.actions;
188 NSLog(@"result has %d actions", actions ? 0 : actions.count);
190 [self updateToolbar];
193 - (void)decoder:(Decoder *)decoder didDecodeImage:(UIImage *)image withResult:(TwoDDecoderResult *)twoDResult {
194 [self presentResultForString:twoDResult.text];
196 // save the scan to the shared database
197 [[Database sharedDatabase] addScanWithText:twoDResult.text];
199 [self performResultAction:self];
202 - (void)decoder:(Decoder *)decoder failedToDecodeImage:(UIImage *)image reason:(NSString *)reason {
203 [self showMessage:reason];
204 [self updateToolbar];
208 // UIImagePickerControllerDelegate methods
210 - (void)imagePickerController:(UIImagePickerController *)picker
211 didFinishPickingImage:(UIImage *)image
212 editingInfo:(NSDictionary *)editingInfo
215 NSLog(@"picked image size = (%f, %f)", image.size.width, image.size.height);
217 UIImage *originalImage = [editingInfo objectForKey:UIImagePickerControllerOriginalImage];
219 NSLog(@"original image size = (%f, %f)", originalImage.size.width, originalImage.size.height);
221 NSValue *cropRectValue = [editingInfo objectForKey:UIImagePickerControllerCropRect];
223 CGRect cropRect = [cropRectValue CGRectValue];
224 NSLog(@"crop rect = (%f, %f) x (%f, %f)", CGRectGetMinX(cropRect), CGRectGetMinY(cropRect), CGRectGetWidth(cropRect), CGRectGetHeight(cropRect));
229 [[picker parentViewController] dismissModalViewControllerAnimated:YES];
232 [self.decoder decodeImage:image];
234 [self updateToolbar];
237 - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker
239 [picker dismissModalViewControllerAnimated:YES];
241 [self updateToolbar];
244 - (void)navigationController:(UINavigationController *)navigationController
245 didShowViewController:(UIViewController *)viewController
246 animated:(BOOL)animated {
250 - (void)navigationController:(UINavigationController *)navigationController
251 willShowViewController:(UIViewController *)viewController
252 animated:(BOOL)animated {
256 - (void)performAction:(ResultAction *)action {
257 [action performActionWithController:self shouldConfirm:NO];
260 - (void)confirmAndPerformAction:(ResultAction *)action {
261 [action performActionWithController:self shouldConfirm:YES];
265 - (IBAction)performResultAction:(id)sender {
266 if (self.result == nil) {
267 NSLog(@"no result to perform an action on!");
271 if (self.actions == nil || self.actions.count == 0) {
272 NSLog(@"result has no actions to perform!");
276 if (self.actions.count == 1) {
277 ResultAction *action = [self.actions lastObject];
279 NSLog(@"Result has the single action, (%@) '%@', performing it",
280 NSStringFromClass([action class]), [action title]);
282 [self performSelector:@selector(confirmAndPerformAction:)
287 NSLog(@"Result has multiple actions, popping up an action sheet");
289 UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithFrame:self.view.bounds];
291 for (ResultAction *action in self.actions) {
292 [actionSheet addButtonWithTitle:[action title]];
295 int cancelIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", @"")];
296 actionSheet.cancelButtonIndex = cancelIndex;
298 actionSheet.delegate = self;
300 [actionSheet showFromToolbar:self.toolbar];
304 - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
305 if (buttonIndex < self.actions.count) {
306 int actionIndex = buttonIndex;
307 ResultAction *action = [self.actions objectAtIndex:actionIndex];
308 [self performSelector:@selector(performAction:)
314 - (IBAction)showArchive:(id)sender {
315 ArchiveController *archiveController = [[ArchiveController alloc] initWithDecoderViewController:self];
316 [[self navigationController] pushViewController:archiveController animated:true];
317 [archiveController release];
320 - (void)showScan:(Scan *)scan {
321 [self.imageView setImage:nil];
322 [self presentResultForString:scan.text];
323 [[self navigationController] popToViewController:self animated:YES];