2 // EditMetadataViewController.m
5 // Copyright 2011 GRNET S.A. All rights reserved.
7 // Redistribution and use in source and binary forms, with or
8 // without modification, are permitted provided that the following
11 // 1. Redistributions of source code must retain the above
12 // copyright notice, this list of conditions and the following
15 // 2. Redistributions in binary form must reproduce the above
16 // copyright notice, this list of conditions and the following
17 // disclaimer in the documentation and/or other materials
18 // provided with the distribution.
20 // THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
21 // OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
24 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 // AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
33 // The views and conclusions contained in the software and
34 // documentation are those of the authors and should not be
35 // interpreted as representing official policies, either expressed
36 // or implied, of GRNET S.A.
38 #import "EditMetadataViewController.h"
39 #import "AccountManager.h"
40 #import "UIViewController+Conveniences.h"
44 @implementation EditMetadataViewController
47 @synthesize container, account, object;
49 @synthesize metadataKey;
50 @synthesize metadataValue;
51 @synthesize deleteEnabled;
55 #define kDeleteMetadata 2
63 [metadataKey release];
64 [metadataValue release];
68 - (void)didReceiveMemoryWarning
70 // Releases the view if it doesn't have a superview.
71 [super didReceiveMemoryWarning];
73 // Release any cached data, images, etc that aren't in use.
76 #pragma mark - View lifecycle
85 [super viewDidUnload];
88 - (void)viewWillAppear:(BOOL)animated
90 [super viewWillAppear:animated];
93 - (void)viewDidAppear:(BOOL)animated
95 [super viewDidAppear:animated];
98 - (void)viewWillDisappear:(BOOL)animated
100 [super viewWillDisappear:animated];
103 - (void)viewDidDisappear:(BOOL)animated
105 [super viewDidDisappear:animated];
108 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
109 return (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) || (toInterfaceOrientation == UIInterfaceOrientationPortrait);
112 #pragma mark - Table view data source
114 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
116 return (deleteEnabled)? 3:2;
119 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
121 if (section == kMetadata)
127 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
129 static NSString *CellIdentifier = @"Cell";
130 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
132 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
134 CGRect bounds = [cell.contentView bounds];
135 CGRect rect = CGRectInset(bounds, 20.0, 10.0);
136 UITextField *textField = [[UITextField alloc] initWithFrame:rect];
137 [textField setFrame:rect];
138 [textField setClearButtonMode:UITextFieldViewModeWhileEditing];
139 [textField setBackgroundColor:[UIColor whiteColor]];
140 [textField setOpaque:YES];
141 [textField setAutocorrectionType:UITextAutocorrectionTypeNo];
142 [textField setAutocapitalizationType:UITextAutocapitalizationTypeNone];
143 [textField setDelegate:self];
145 if (indexPath.section == kMetadata) {
146 if (indexPath.row == 0) {
147 [textField setReturnKeyType:UIReturnKeyNext];
148 textField.placeholder = @"Key";
149 textField.text = metadataKey;
152 else if (indexPath.row == 1) {
153 textField.placeholder = @"Value";
154 textField.text = metadataValue;
158 cell.selectionStyle = UITableViewCellSelectionStyleNone;
159 [cell.contentView addSubview:textField];
161 else if (indexPath.section == kSaveMedata)
162 cell.textLabel.text = @"Save";
163 else if (indexPath.section == kDeleteMetadata)
164 cell.textLabel.text = @"Delete";
170 #pragma mark - Table view delegate
172 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
174 NSString *activityMessage;
175 NSIndexPath *keyCellIndexPath;
176 NSIndexPath *valueCellIndexPath;
177 UITableViewCell *cell;
178 switch (indexPath.section) {
180 keyCellIndexPath = [NSIndexPath indexPathForRow:0 inSection:kMetadata];
181 cell = [self.tableView cellForRowAtIndexPath:keyCellIndexPath];
182 UITextField *textField = [[cell.contentView subviews] objectAtIndex:0];
183 NSString *newMetadataKey = textField.text;
185 if ([newMetadataKey length] == 0
186 || [[newMetadataKey stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
187 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
188 [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
192 valueCellIndexPath = [NSIndexPath indexPathForRow:1 inSection:kMetadata];
193 cell = [self.tableView cellForRowAtIndexPath:valueCellIndexPath];
194 textField = [[cell.contentView subviews] objectAtIndex:0];
195 NSString *newMetadataValue = textField.text;
197 activityMessage = @"Saving metadata";
199 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
200 [activityIndicatorView addToView:self.view];
202 [object.metadata removeObjectForKey:metadataKey];
203 [object.metadata setObject:newMetadataValue forKey:newMetadataKey];
204 [self.account.manager writeObjectMetadata:container object:object];
205 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
207 queue:[NSOperationQueue mainQueue]
208 usingBlock:^(NSNotification *notification)
210 self.metadataKey = newMetadataKey;
211 self.metadataValue = newMetadataValue;
213 [activityIndicatorView removeFromSuperviewAndRelease];
214 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
215 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
218 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed"
220 queue:[NSOperationQueue mainQueue]
221 usingBlock:^(NSNotification *notification)
223 [object.metadata removeObjectForKey:newMetadataKey];
224 [object.metadata setObject:metadataValue forKey:metadataKey];
225 [activityIndicatorView removeFromSuperviewAndRelease];
226 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
227 [self alert:@"There was a problem saving the metadata." request:[notification.userInfo objectForKey:@"request"]];
229 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
233 case kDeleteMetadata:
234 activityMessage = @"Deleting metadata";
235 activityIndicatorView = [[ActivityIndicatorView alloc] initWithFrame:[ActivityIndicatorView frameForText:activityMessage] text:activityMessage];
236 [activityIndicatorView addToView:self.view];
238 [object.metadata removeObjectForKey:metadataKey];
239 [self.account.manager writeObjectMetadata:container object:object];
240 successObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataSucceeded"
242 queue:[NSOperationQueue mainQueue]
243 usingBlock:^(NSNotification *notification)
245 [activityIndicatorView removeFromSuperviewAndRelease];
246 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
247 self.metadataKey = @"";
248 self.metadataValue = @"";
250 [self.tableView reloadData];
251 [[NSNotificationCenter defaultCenter] removeObserver:successObserver];
254 failureObserver = [[NSNotificationCenter defaultCenter] addObserverForName:@"writeObjectMetadataFailed"
256 queue:[NSOperationQueue mainQueue]
257 usingBlock:^(NSNotification *notification)
259 [object.metadata setObject:metadataValue forKey:metadataKey];
260 [activityIndicatorView removeFromSuperviewAndRelease];
261 [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
262 [self alert:@"There was a problem saving the metadata." request:[notification.userInfo objectForKey:@"request"]];
264 [[NSNotificationCenter defaultCenter] removeObserver:failureObserver];
271 #pragma mark - Textfield delegate
273 - (void)textFieldDidEndEditing:(UITextField *)textField
275 if ([textField tag] == 0) {
276 if ([textField.text length] == 0
277 || [[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0) {
278 [self alert:@"Invalid input" message:@"Metadata key cannot be empty"];
285 - (BOOL)textFieldShouldReturn:(UITextField *)textField
288 if ([textField returnKeyType] == UIReturnKeyNext)
290 NSInteger nextTag = [textField tag] + 1;
291 UIView *nextTextField = [self.tableView viewWithTag:nextTag];
292 [nextTextField becomeFirstResponder];
296 [textField resignFirstResponder];