OSDN Git Service

3079b587b3df4b8f73a6543f0ce33bcbf8bc9b22
[tombo/Tombo.git] / iOS / Tombo / Tombo / MasterViewController.m
1 #import "MasterViewController.h"
2 #import "EditViewController.h"
3 #import "DetailViewController.h"
4 #import "EditCancelAlert.h"
5 #import "NewFolderAlert.h"
6
7 #import "Storage.h"
8 #import "FileItem.h"
9 #import "PasswordManager.h"
10
11 @interface MasterViewController () <UITableViewDelegate, UISplitViewControllerDelegate> {
12     NSMutableArray *_objects;
13     Storage *storage;
14     PasswordManager *passwordManager;
15     
16     UIImage *imgFolder;
17     UIImage *imgDocument;
18     UIImage *imgUp;
19     UIImage *imgKey;
20 }
21 @end
22
23 @implementation MasterViewController
24
25 @synthesize detailViewController = _detailViewController;
26
27 - (void)awakeFromNib
28 {
29     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
30         self.clearsSelectionOnViewWillAppear = NO;
31         self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
32     }
33     [super awakeFromNib];
34 }
35
36 - (void)viewDidLoad
37 {
38     [super viewDidLoad];
39         // Do any additional setup after loading the view, typically from a nib.
40     self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
41     self.detailViewController.master = self;
42     self.splitViewController.delegate = self;
43     
44     passwordManager = [[PasswordManager alloc] init];
45     
46     UIBarButtonItem *newFolderBtn = [[UIBarButtonItem alloc] initWithTitle:@"New Folder"
47                                                                      style:UIBarButtonItemStyleBordered
48                                                                     target:self
49                                                                     action:@selector(createNewFolder:)];
50     [self setToolbarItems:[NSArray arrayWithObjects:newFolderBtn, nil] animated:YES];
51     [self.navigationController setToolbarHidden:NO];
52     
53     imgFolder = nil;
54     imgDocument = nil;
55     if (!storage) {
56         storage = [Storage init];
57     }
58     
59     // Load initial items.
60     [self insertItems];
61 }
62
63 - (void)viewDidUnload
64 {
65     [super viewDidUnload];
66     // Release any retained subviews of the main view.
67     storage = nil;
68 }
69
70 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
71 {
72     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
73         return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
74     } else {
75         
76         return YES;
77     }
78 }
79
80 - (void)openNewNote:(id)sender
81 {
82     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
83         // iPhone : Transit to detail view.
84         [self performSegueWithIdentifier:@"newNote" sender:self];
85     } else {
86         // iPad : Clear detail view.
87     }
88 }
89
90 - (void)createNewFolder:(id)sender {
91     NewFolderAlert *alert = [[NewFolderAlert alloc] initWithDefault];
92     NSString *folderName = [alert showAndWait];
93     if (folderName) {
94         FileItem *item = [storage newFolder:folderName];
95         [self insertItem:item];
96     }
97 }
98 #pragma mark - Item operations
99
100 - (void)insertItems {
101     for (FileItem *file in [storage listItems]) {
102         [self insertItem: file];
103     }    
104     if (!storage.isTopDir) {
105         FileItem *up = [FileItem allocWithName:@"UP"];
106         up.isUp = YES;
107         [self insertItem: up];
108     }
109 }
110
111 - (void)removeAllItems {
112     NSUInteger n = [_objects count];
113     
114     NSMutableArray *rmItems = [[NSMutableArray alloc] initWithCapacity:n];
115     for (int i = 0; i < n; i++) {
116         NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
117         [rmItems addObject: indexPath];
118     }
119     [_objects removeAllObjects];
120     [self.tableView deleteRowsAtIndexPaths: rmItems withRowAnimation:UITableViewRowAnimationAutomatic];
121 }
122
123 - (void)insertItem:(FileItem *)item {
124     if (!_objects) {
125         _objects = [[NSMutableArray alloc] init];
126     }
127     NSUInteger n = [_objects count];
128     NSUInteger i;
129     for (i = 0; i < n; i++) {
130         if (item.isUp) break;
131         
132         FileItem *cur = [_objects objectAtIndex:i];
133         NSComparisonResult r = [item compare:cur];
134         if (r == NSOrderedAscending || r == NSOrderedSame) {
135             break;
136         }
137     }
138     
139     [_objects insertObject:item atIndex:i];
140     NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
141     [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
142                           withRowAnimation:UITableViewRowAnimationAutomatic];
143 }
144
145 - (void) deleteItem:(FileItem *)item {
146     NSUInteger i = 0;
147     for (FileItem *f in _objects) {
148         if ([f.name isEqualToString: item.name]) {
149             [_objects removeObjectAtIndex:i];
150             NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
151             [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
152                                   withRowAnimation:UITableViewRowAnimationAutomatic];
153             break;
154         }
155         i++;
156     }
157 }
158
159 - (BOOL)splitViewController:(UISplitViewController *)svc shouldHideViewController:(UIViewController *)vc inOrientation:(UIInterfaceOrientation)orientation {
160     return NO;
161 }
162
163 #pragma mark - Table View
164
165 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
166 {
167     return 1;
168 }
169
170 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
171 {
172     return _objects.count;
173 }
174
175 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
176 {
177     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
178
179     FileItem *fItem = [_objects objectAtIndex:indexPath.row];
180     cell.textLabel.text = [fItem name];
181     if (fItem.isUp) {
182         if (!imgUp) {
183             imgUp = [UIImage imageNamed:@"sub_blue_up-32"];
184         }
185         cell.imageView.image = imgUp;
186     } else if (fItem.isCrypt) {
187         if (!imgKey) {
188             imgKey = [UIImage imageNamed:@"key-32"];
189         }
190         cell.imageView.image = imgKey;
191     } else if (fItem.isDirectory) {
192         if (!imgFolder) {
193             imgFolder = [UIImage imageNamed:@"Folder-32"];
194
195         }
196         cell.imageView.image = imgFolder;
197     } else {
198         if (!imgDocument) {
199             imgDocument = [UIImage imageNamed:@"TextDocument-32"];
200         }
201         cell.imageView.image = imgDocument;
202     }
203     return cell;
204 }
205
206 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
207 {
208     // Return NO if you do not want the specified item to be editable.
209     FileItem *item = [_objects objectAtIndex:indexPath.row];
210     if (item.isUp) return NO;
211     return YES;
212 }
213
214 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
215 {
216     if (editingStyle == UITableViewCellEditingStyleDelete) {
217         FileItem *item = [_objects objectAtIndex:indexPath.row];
218         [storage deleteItem:item];
219         
220         [_objects removeObjectAtIndex:indexPath.row];
221         [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
222                          withRowAnimation:UITableViewRowAnimationFade];
223     } else if (editingStyle == UITableViewCellEditingStyleInsert) {
224         // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
225     }
226 }
227
228 /*
229 // Override to support rearranging the table view.
230 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
231 {
232 }
233 */
234
235 /*
236 // Override to support conditional rearranging of the table view.
237 - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
238 {
239     // Return NO if you do not want the item to be re-orderable.
240     return YES;
241 }
242 */
243
244 - (void)transitToDetailView:(FileItem *)item {
245     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
246         self.detailViewController.item = item;
247     } else {
248         [self performSegueWithIdentifier:@"showNote" sender:self];
249     }
250 }
251
252 // Select Row(iPhone/iPad)
253 // set item for iPad
254 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
255 {
256     FileItem *item = [_objects objectAtIndex:indexPath.row];
257     if (item.isUp) {
258         // switch view items
259         [self removeAllItems];
260         [storage updir];
261         [self insertItems];        
262     } else if (item.isDirectory) {
263         [self removeAllItems];
264         [storage chdir: item.name];
265         [self insertItems];        
266     } else {
267         if (item.isCrypt) {
268             if ([passwordManager preparePassword]) {
269                 // Check to success decrypt and transit.
270                 NSString *note = [Storage loadCryptFile:item.path password:passwordManager.password];
271                 if (note) {
272                     [self transitToDetailView:item];
273                 } else {
274                     UIAlertView *decryptFail = [[UIAlertView alloc] initWithTitle:@"Error"
275                                                                           message:@"Decryption failed." 
276                                                                          delegate:nil 
277                                                                 cancelButtonTitle:@"OK" 
278                                                                 otherButtonTitles:nil];
279                     [decryptFail show];
280                     // Invalid password so clear it.
281                     passwordManager.password = nil;
282                 }
283             }
284         } else {
285             [self transitToDetailView:item];
286         }
287     }
288 }
289
290 // set item (for iPhone)
291 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
292 {
293     if ([[segue identifier] isEqualToString:@"newNote"]) {
294         EditViewController *edit = (EditViewController*)[[[segue destinationViewController] viewControllers] objectAtIndex:0];
295         edit.detailItem = [storage newItem];
296         edit.delegate = self;
297     } else if ([[segue identifier] isEqualToString:@"editNote"]) {
298         // This path is used only iPhone
299         EditViewController *edit = (EditViewController*)[[[segue destinationViewController] viewControllers] objectAtIndex:0];
300         NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
301         FileItem *item = [_objects objectAtIndex:indexPath.row];
302         edit.detailItem = item;
303         edit.delegate = self;
304     } else if ([[segue identifier] isEqualToString:@"showNote"]) {
305         DetailViewController *detail = [segue destinationViewController];
306         self.detailViewController = detail;
307         NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
308         FileItem *item = [_objects objectAtIndex:indexPath.row];
309         detail.item = item;
310         detail.storage = storage;
311         detail.passwordManager = passwordManager;
312         detail.master = self;
313         detail.delegate = self;
314     }
315 }
316
317 #pragma mark - EditViewControllerDelegate
318
319 - (void)editViewControllerDidFinish:(EditViewController *)controller {
320     if (controller.isModify) {
321         // save note
322         if (![controller.detailItem isNewItem]) {
323             [self deleteItem:controller.detailItem];
324         }
325         NSString *note = controller.detailText.text;
326         FileItem *item;
327         if (controller.detailItem.isCrypt) {
328             if ([passwordManager preparePasswordConfirm]) {
329                 item = [storage saveCrypt:note item:controller.detailItem password:passwordManager.password];
330             } else {
331                 // Don't dismiss view.
332                 return;
333             }
334         } else {
335             item = [storage savePlain:note item:controller.detailItem];
336         }
337         controller.isModify = NO;
338         
339         self.detailViewController.item = item;
340
341         [self insertItem:item];
342     }
343     [self dismissModalViewControllerAnimated:YES];
344 }
345
346 - (void)editViewControllerDidCancel:(EditViewController *)controller {
347     if (controller.isModify) {
348         EditCancelAlert *cancel = [[EditCancelAlert alloc] initWithDefault];
349         if ([cancel showAndWait]) {
350             [self dismissModalViewControllerAnimated:YES];                    
351         }
352     } else {
353         [self dismissModalViewControllerAnimated:YES];                
354     }
355 }
356
357 #pragma mark - DetailViewDelegate
358
359 -(void)detailViewFileItemChanged:(FileItem*)oldItem to:(FileItem *)newItem {
360     [self deleteItem:oldItem];
361     [self insertItem:newItem];
362 }
363
364 @end