complete settings page rework
authorkoda
Tue, 20 Jul 2010 05:37:58 +0200
changeset 3660 bc125bea5849
parent 3659 f8d5ac50e307
child 3661 2378ada8a6ee
complete settings page rework
project_files/HedgewarsMobile/Classes/CommodityFunctions.m
project_files/HedgewarsMobile/Classes/EditableCellView.h
project_files/HedgewarsMobile/Classes/EditableCellView.m
project_files/HedgewarsMobile/Classes/GameSetup.m
project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h
project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m
project_files/HedgewarsMobile/Classes/InGameMenuViewController.m
project_files/HedgewarsMobile/Classes/MainMenuViewController.m
project_files/HedgewarsMobile/Classes/MapConfigViewController.m
project_files/HedgewarsMobile/Classes/OverlayViewController.m
project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m
project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m
project_files/HedgewarsMobile/Classes/SingleTeamViewController.h
project_files/HedgewarsMobile/Classes/SingleTeamViewController.m
project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m
project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m
--- a/project_files/HedgewarsMobile/Classes/CommodityFunctions.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/CommodityFunctions.m	Tue Jul 20 05:37:58 2010 +0200
@@ -31,7 +31,7 @@
         [hog release];
     }
     
-    NSDictionary *theTeam = [[NSDictionary alloc] initWithObjectsAndKeys:@"0",@"hash", nameWithoutExt,@"teamname",
+    NSDictionary *theTeam = [[NSDictionary alloc] initWithObjectsAndKeys:@"0",@"hash",
                              @"Statue",@"grave", @"Plane",@"fort", @"Default",@"voicepack",
                              @"hedgewars",@"flag", hedgehogs,@"hedgehogs", nil];
     [hedgehogs release];
--- a/project_files/HedgewarsMobile/Classes/EditableCellView.h	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/EditableCellView.h	Tue Jul 20 05:37:58 2010 +0200
@@ -8,19 +8,25 @@
 
 #import <UIKit/UIKit.h>
 
+#define MAX_STRING_LENGTH 64
+
 @protocol EditableCellViewDelegate <NSObject>
 
--(void) saveTextFieldValue:(NSString *)textString;
+-(void) saveTextFieldValue:(NSString *)textString withTag:(NSInteger) tagValue;
 
 @end
 
 @interface EditableCellView : UITableViewCell <UITextFieldDelegate> {
     id<EditableCellViewDelegate> delegate;
     UITextField *textField;
+    
+@private
+    NSString *oldValue;
 }
 
 @property (nonatomic,assign) id<EditableCellViewDelegate> delegate;
 @property (nonatomic,retain,readonly) UITextField *textField;
+@property (nonatomic,retain) NSString *oldValue;
 
 -(void) replyKeyboard;
 -(void) cancel:(id) sender;
--- a/project_files/HedgewarsMobile/Classes/EditableCellView.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/EditableCellView.m	Tue Jul 20 05:37:58 2010 +0200
@@ -9,8 +9,10 @@
 #import "EditableCellView.h"
 #import "CommodityFunctions.h"
 
+#define MAX_STRING_LENGTH 64
+
 @implementation EditableCellView
-@synthesize delegate, textField;
+@synthesize delegate, textField, oldValue;
 
 -(id) initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
     if ((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
@@ -28,6 +30,8 @@
         
         [self.contentView addSubview:textField];
         [textField release];
+        
+        oldValue = nil;
     }
     return self;
 }
@@ -38,7 +42,11 @@
     CGRect contentRect = self.contentView.bounds;
     CGFloat boundsX = contentRect.origin.x;
     
-    textField.frame = CGRectMake(boundsX+10, 11, 250, [UIFont labelFontSize] + 2);
+    int offset = 0;
+    if (self.imageView != nil)
+        offset = self.imageView.frame.size.width;
+    
+    textField.frame = CGRectMake(boundsX+offset+10, 10, 250, [UIFont labelFontSize] + 4);
 }
 
 /*
@@ -49,6 +57,7 @@
 */
 
 -(void) dealloc {
+    [oldValue release];
     [textField release];
     [super dealloc];
 }
@@ -57,8 +66,7 @@
 #pragma mark textField delegate
 // limit the size of the field to 64 characters like in original frontend
 -(BOOL) textField:(UITextField *)aTextField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
-    int limit = 64;
-    return !([aTextField.text length] > limit && [string length] > range.length);
+    return !([aTextField.text length] > MAX_STRING_LENGTH && [string length] > range.length);
 }
 
 // allow editing only if delegate is set 
@@ -68,9 +76,11 @@
 
 // the textfield is being modified, update the navigation controller
 -(void) textFieldDidBeginEditing:(UITextField *)aTextField{
-    // don't scroll when editing
+    // don't interact with table below
     ((UITableView*)[self superview]).scrollEnabled = NO;
     
+    self.oldValue = self.textField.text;
+    
     UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel",@"")
                                                                      style:UIBarButtonItemStylePlain
                                                                     target:self
@@ -86,11 +96,17 @@
     [saveButton release];
 }
 
-
+/* with this a field might remain in editing status even if the view moved;
+   use method below instead that allows some more interaction
 // don't accept 0-length strings
 -(BOOL) textFieldShouldEndEditing:(UITextField *)aTextField {
     return ([aTextField.text length] > 0); 
 }
+*/
+
+-(BOOL) textFieldShouldReturn:(UITextField *)aTextField {
+    return ([aTextField.text length] > 0); 
+}
 
 // the textfield has been modified, tell the delegate to do something
 -(void) textFieldDidEndEditing:(UITextField *)aTextField{
@@ -106,7 +122,8 @@
 
 // the user pressed cancel so hide keyboard
 -(void) cancel:(id) sender {
-    [self.textField resignFirstResponder];
+    self.textField.text = self.oldValue;
+    [self save:sender];
 }
 
 // send the value to the delegate
@@ -114,8 +131,13 @@
     if (delegate == nil)
         return;
     
-    [delegate saveTextFieldValue:self.textField.text];
+    // don't save if the textfield is invalid
+    if (![self textFieldShouldReturn:textField])
+        return;
+    
+    [delegate saveTextFieldValue:self.textField.text withTag:self.tag];
     [self.textField resignFirstResponder];
+    self.oldValue = nil;
 }
 
 @end
--- a/project_files/HedgewarsMobile/Classes/GameSetup.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/GameSetup.m	Tue Jul 20 05:37:58 2010 +0200
@@ -56,7 +56,7 @@
     [teamFile release];
     
     NSString *teamHashColorAndName = [[NSString alloc] initWithFormat:@"eaddteam %@ %@ %@", 
-                                      [teamData objectForKey:@"hash"], [teamColor stringValue], [teamData objectForKey:@"teamname"]];
+                                      [teamData objectForKey:@"hash"], [teamColor stringValue], [teamName stringByDeletingPathExtension]];
     [self sendToEngine: teamHashColorAndName];
     [teamHashColorAndName release];
     
--- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.h	Tue Jul 20 05:37:58 2010 +0200
@@ -15,7 +15,6 @@
     UISwitch *musicSwitch;
     UISwitch *soundSwitch;
     UISwitch *altDamageSwitch;
-    BOOL isWriteNeeded;
 }
 
 @property (nonatomic, retain) NSMutableDictionary *settingsDictionary;
@@ -24,8 +23,4 @@
 @property (nonatomic, retain) UISwitch *soundSwitch;
 @property (nonatomic, retain) UISwitch *altDamageSwitch;
 
-#define kNetworkFields 0
-#define kAudioFields 1
-#define kOtherFields 2
-
 @end
--- a/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/GeneralSettingsViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -8,6 +8,7 @@
 
 #import "GeneralSettingsViewController.h"
 #import "CommodityFunctions.h"
+#import "EditableCellView.h"
 
 @implementation GeneralSettingsViewController
 @synthesize settingsDictionary, textFieldBeingEdited, musicSwitch, soundSwitch, altDamageSwitch;
@@ -26,19 +27,15 @@
 }
 
 // set the new value
--(BOOL) save:(id) sender {
+-(void) save:(id) sender {
     if (textFieldBeingEdited != nil) {
-        if (textFieldBeingEdited.tag == 0) {
+        if (textFieldBeingEdited.tag == 0)
             [self.settingsDictionary setObject:textFieldBeingEdited.text forKey:@"username"];
-        } else {
+        else
             [self.settingsDictionary setObject:textFieldBeingEdited.text forKey:@"password"];
-        }
         
-        isWriteNeeded = YES;
         [self.textFieldBeingEdited resignFirstResponder];
-        return YES;
     }
-    return NO;
 }
 
 // the textfield is being modified, update the navigation controller
@@ -68,11 +65,9 @@
 
 // limit the size of the field to 64 characters like in original frontend
 -(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
-    int limit = 64;
-    return !([textField.text length] > limit && [string length] > range.length);
+    return !([textField.text length] > MAX_STRING_LENGTH && [string length] > range.length);
 }
 
-
 #pragma mark -
 #pragma mark View Lifecycle
 -(void) viewDidLoad {
@@ -91,7 +86,6 @@
 
 -(void) viewWillAppear:(BOOL)animated {
     [self.tableView setContentOffset:CGPointMake(0,0) animated:NO];
-    isWriteNeeded = NO;
     
     musicSwitch.on = [[settingsDictionary objectForKey:@"music"] boolValue];
     soundSwitch.on = [[settingsDictionary objectForKey:@"sound"] boolValue];
@@ -101,13 +95,8 @@
 }
 
 -(void) viewWillDisappear:(BOOL)animated {
-    [super viewWillDisappear:animated];
-    
-    if (isWriteNeeded) {
-        NSLog(@"writing preferences to file");
-        [self.settingsDictionary writeToFile:SETTINGS_FILE() atomically:YES];
-        isWriteNeeded = NO;
-    }
+    [super viewWillDisappear:animated];    
+    [self.settingsDictionary writeToFile:SETTINGS_FILE() atomically:YES];
 }
 
 #pragma mark -
@@ -118,23 +107,19 @@
         [musicSwitch setOn:NO animated:YES];
         [self.settingsDictionary setObject:[NSNumber numberWithBool:musicSwitch.on] forKey:@"music"];
     }
-    isWriteNeeded = YES;
 }
 
 // if the sound system is off, don't enable background music 
 -(void) dontTurnOnMusic:(id) sender {
-    if (NO == self.soundSwitch.on) {
+    if (NO == self.soundSwitch.on)
         [musicSwitch setOn:NO animated:YES];
-    } else {
+    else
         [self.settingsDictionary setObject:[NSNumber numberWithBool:musicSwitch.on] forKey:@"music"];
-        isWriteNeeded = YES;
-    }
 }
 
 -(void) justUpdateDictionary:(id) sender {
     UISwitch *theSwitch = (UISwitch *)sender;
     [self.settingsDictionary setObject:[NSNumber numberWithBool:theSwitch.on] forKey:@"alternate"];
-    isWriteNeeded = YES;
 }
 
 #pragma mark -
@@ -145,13 +130,13 @@
 
 -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
     switch (section) {
-        case kNetworkFields:
+        case 0:     // user and pass
             return 2;
             break;
-        case kAudioFields:
+        case 1:     // audio
             return 2;
             break;
-        case kOtherFields:
+        case 2:     // alternate damage
             return 1;
             break;
         default:
@@ -165,42 +150,37 @@
     NSInteger row = [indexPath row];
     NSInteger section = [indexPath section];
     
-    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:cellIdentifier];
-    if (nil == cell) {
-        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
-        if (section == kNetworkFields) {
-            UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(-15, 10, 100, 25)];
-            label.textAlignment = UITextAlignmentRight;
-            label.backgroundColor = [UIColor clearColor];
-            label.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2];
-            if (row == 0) 
-                label.text = NSLocalizedString(@"Nickname","from the settings table");
-            else 
-                label.text = NSLocalizedString(@"Password","from the settings table");
-            [cell.contentView addSubview:label];
-            [label release];
-            
-            UITextField *aTextField = [[UITextField alloc] initWithFrame:
-                                       CGRectMake(110, 12, (cell.frame.size.width + cell.frame.size.width/3) - 90, 25)];
-            aTextField.clearsOnBeginEditing = NO;
-            aTextField.returnKeyType = UIReturnKeyDone;
-            aTextField.adjustsFontSizeToFitWidth = YES;
-            aTextField.delegate = self;
-            aTextField.tag = row;
-            aTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
-            [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit];
-            [cell.contentView addSubview:aTextField];
-            [aTextField release];
-        }
-    }
-    
-    cell.accessoryType = UITableViewCellAccessoryNone;
-    cell.selectionStyle = UITableViewCellSelectionStyleNone;
-    cell.imageView.image = nil;
-    
+    UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:cellIdentifier];    
     UITextField *aTextField;
     switch (section) {
-        case kNetworkFields:
+        case 0:
+            if (nil == cell) {
+                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
+                if (section == 0) {
+                    UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(-9, 10, 100, [UIFont labelFontSize] + 4)];
+                    label.textAlignment = UITextAlignmentRight;
+                    label.backgroundColor = [UIColor clearColor];
+                    label.font = [UIFont boldSystemFontOfSize:[UIFont labelFontSize]];
+                    if (row == 0) 
+                        label.text = NSLocalizedString(@"Nickname","from the settings table");
+                    else 
+                        label.text = NSLocalizedString(@"Password","from the settings table");
+                    [cell.contentView addSubview:label];
+                    [label release];
+                    
+                    UITextField *aTextField = [[UITextField alloc] initWithFrame:
+                                               CGRectMake(110, 10, (cell.frame.size.width + cell.frame.size.width/3) - 90, [UIFont labelFontSize] + 4)];
+                    aTextField.clearsOnBeginEditing = NO;
+                    aTextField.returnKeyType = UIReturnKeyDone;
+                    aTextField.adjustsFontSizeToFitWidth = YES;
+                    aTextField.delegate = self;
+                    aTextField.tag = row;
+                    aTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
+                    [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit];
+                    [cell.contentView addSubview:aTextField];
+                    [aTextField release];
+                }
+            }
             for (UIView *oneView in cell.contentView.subviews) 
                 if ([oneView isMemberOfClass:[UITextField class]]) 
                     aTextField = (UITextField *)oneView;
@@ -209,6 +189,7 @@
                 case 0:                    
                     aTextField.placeholder = NSLocalizedString(@"Insert your username (if you have one)",@"");
                     aTextField.text = [self.settingsDictionary objectForKey:@"username"];
+                    aTextField.secureTextEntry = NO;
                     break;
                 case 1:                    
                     aTextField.placeholder = NSLocalizedString(@"Insert your password",@"");
@@ -220,7 +201,11 @@
             }
             break;
             
-        case kAudioFields:
+            cell.accessoryView = nil;
+        case 1:
+            if (nil == cell)
+                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
+
             switch (row) {
                 case 0:
                     cell.textLabel.text = NSLocalizedString(@"Sound", @"");
@@ -235,31 +220,38 @@
             }
             break;
             
-        case kOtherFields:
-            cell.selectionStyle = UITableViewCellSelectionStyleNone;
+        case 2:
+            if (nil == cell)
+                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
+
             cell.textLabel.text = NSLocalizedString(@"Alternate Damage", @"");
             cell.accessoryView = altDamageSwitch;
             break;
         default:
             break;
     }
+    
+    cell.accessoryType = UITableViewCellAccessoryNone;
+    cell.selectionStyle = UITableViewCellSelectionStyleNone;
+    cell.imageView.image = nil;
+    
     return cell;
 }
 
 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
     NSString *sectionTitle = nil;
     switch (section) {
-        case kNetworkFields:
+        case 0:
             sectionTitle = NSLocalizedString(@"Network Configuration", @"");
             break;
-        case kAudioFields:
+        case 1:
             sectionTitle = NSLocalizedString(@"Audio Preferences", @"");
             break;
-        case kOtherFields:
+        case 2:
             sectionTitle = NSLocalizedString(@"Other Settings", @"");
             break;
         default:
-            NSLog(@"Nope");
+            DLog(@"Nope");
             break;
     }
     return sectionTitle;
@@ -313,7 +305,7 @@
 #pragma mark Table view delegate
 -(void) tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
     UITableViewCell *cell;
-    if (kNetworkFields == [indexPath section]) {
+    if (0 == [indexPath section]) {
         cell = [aTableView cellForRowAtIndexPath:indexPath];
         for (UIView *oneView in cell.contentView.subviews) {
             if ([oneView isMemberOfClass:[UITextField class]]) {
--- a/project_files/HedgewarsMobile/Classes/InGameMenuViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/InGameMenuViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -141,7 +141,7 @@
                 HW_pause();
             break;
         default:
-            NSLog(@"Warning: unset case value in section!");
+            DLog(@"Warning: unset case value in section!");
             break;
     }
     
--- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -54,7 +54,7 @@
 // if it is it blocks user interaction with an alertView until files are created
 -(void) checkFirstRun {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
-    NSLog(@"First time run, creating settings files at %@", SETTINGS_FILE());
+    DLog(@"First time run, creating settings files at %@", SETTINGS_FILE());
     
     // show a popup with an indicator to make the user wait
     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Please wait",@"")
--- a/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/MapConfigViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -39,19 +39,19 @@
     static uint8_t map[128*32];
     
     if (SDLNet_Init() < 0) {
-        NSLog(@"SDLNet_Init: %s", SDLNet_GetError());
+        DLog(@"SDLNet_Init: %s", SDLNet_GetError());
         serverQuit = YES;
     }
     
     // Resolving the host using NULL make network interface to listen
     if (SDLNet_ResolveHost(&ip, NULL, port) < 0) {
-        NSLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
+        DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
         serverQuit = YES;
     }
     
     // Open a connection with the IP provided (listen on the host's port)
     if (!(sd = SDLNet_TCP_Open(&ip))) {
-        NSLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
+        DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), port);
         serverQuit = YES;
     }
     
--- a/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/OverlayViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -195,7 +195,7 @@
             HW_otherKeysUp();
             break;
         default:
-            NSLog(@"Nope");
+            DLog(@"Nope");
             break;
     }
 
--- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m	Tue Jul 20 05:37:58 2010 +0200
@@ -115,7 +115,6 @@
     [application setStatusBarHidden:YES]; 
     
     UIWindow *uiwindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
-    uiwindow.backgroundColor = [UIColor blackColor];
     
     if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
         self.mainViewController = [[MainMenuViewController alloc] initWithNibName:@"MainMenuViewController-iPad" bundle:nil];
@@ -124,9 +123,10 @@
 
     [uiwindow addSubview:self.mainViewController.view];
     [self.mainViewController release];
+    uiwindow.backgroundColor = [UIColor blackColor];
     [uiwindow makeKeyAndVisible];
 
-    // Set working directory to resource path
+    // set working directory to resource path
     [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] resourcePath]];
 }
 
@@ -166,7 +166,6 @@
 }
 
 -(void) applicationDidBecomeActive:(UIApplication *)application {
-    //NSLog(@"%@", NSStringFromSelector(_cmd));
     if (isInGame) {
         HW_pause();
 
--- a/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/SingleSchemeViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -133,7 +133,7 @@
 #pragma mark -
 #pragma mark editableCellView delegate
 // set the new value
--(void) saveTextFieldValue:(NSString *)textString {    
+-(void) saveTextFieldValue:(NSString *)textString withTag:(NSInteger) tagValue {    
     // delete old file
     [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.plist",SCHEMES_DIRECTORY(),self.schemeName] error:NULL];
     // update filename
--- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.h	Tue Jul 20 05:37:58 2010 +0200
@@ -7,6 +7,7 @@
 //
 
 #import <UIKit/UIKit.h>
+#import "EditableCellView.h"
 
 @class HogHatViewController;
 @class GravesViewController;
@@ -14,10 +15,10 @@
 @class FortsViewController;
 @class FlagsViewController;
 @class LevelViewController;
-@interface SingleTeamViewController : UITableViewController <UITextFieldDelegate> {
+
+@interface SingleTeamViewController : UITableViewController <EditableCellViewDelegate> {
     NSMutableDictionary *teamDictionary;
     
-    UITextField *textFieldBeingEdited;
     NSString *teamName;
     UIImage *normalHogSprite;
     
@@ -33,7 +34,6 @@
 }
 
 @property (nonatomic,retain) NSMutableDictionary *teamDictionary;
-@property (nonatomic,retain) UITextField *textFieldBeingEdited;
 @property (nonatomic,retain) NSString *teamName;
 @property (nonatomic,retain) UIImage *normalHogSprite;
 @property (nonatomic,retain) NSArray *secondaryItems;
--- a/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/SingleTeamViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -16,86 +16,34 @@
 #import "CommodityFunctions.h"
 #import "UIImageExtra.h"
 
-#define TEAMNAME_TAG 1234
+#define TEAMNAME_TAG 78789
 
 @implementation SingleTeamViewController
-@synthesize teamDictionary, normalHogSprite, secondaryItems, textFieldBeingEdited, teamName;
-
+@synthesize teamDictionary, normalHogSprite, secondaryItems, teamName;
 
 -(BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) interfaceOrientation {
     return rotationManager(interfaceOrientation);
 }
 
-
 #pragma mark -
-#pragma mark textfield methods
--(void) cancel:(id) sender {
-    if (textFieldBeingEdited != nil)
-        [self.textFieldBeingEdited resignFirstResponder];
-}
-
+#pragma mark editableCellViewDelegate methods
 // set the new value
--(BOOL) save:(id) sender {
-    NSInteger index = textFieldBeingEdited.tag;
-    
-    if (textFieldBeingEdited != nil) {
-        if (TEAMNAME_TAG == index) {
-            if ([textFieldBeingEdited.text length] == 0) 
-                textFieldBeingEdited.text = self.title;
-            [self.teamDictionary setObject:textFieldBeingEdited.text forKey:@"teamname"];
-            self.title = textFieldBeingEdited.text;
-        } else {
-            if ([textFieldBeingEdited.text length] == 0) 
-                textFieldBeingEdited.text = [NSString stringWithFormat:@"hedgehog %d",index];
-            
-            //replace the old value with the new one            
-            NSMutableDictionary *hog = [[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:index];
-            [hog setObject:textFieldBeingEdited.text forKey:@"hogname"];
-        }
-        
+-(void) saveTextFieldValue:(NSString *)textString withTag:(NSInteger) tagValue {
+    if (TEAMNAME_TAG == tagValue) {
+        // delete old file
+        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.teamName] error:NULL];
+        // update filename
+        self.teamName = textString;
+        // save new file
+        [self writeFile];
+    } else {
+        // replace the old value with the new one
+        NSMutableDictionary *hog = [[teamDictionary objectForKey:@"hedgehogs"] objectAtIndex:tagValue];
+        [hog setObject:textString forKey:@"hogname"];
         isWriteNeeded = YES;
-        [self.textFieldBeingEdited resignFirstResponder];
-        return YES;
     }
-    return NO;
 }
 
-// the textfield is being modified, update the navigation controller
--(void) textFieldDidBeginEditing:(UITextField *)aTextField{   
-    self.textFieldBeingEdited = aTextField;
-
-    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel",@"from the hog name table")
-                                                                     style:UIBarButtonItemStylePlain
-                                                                    target:self
-                                                                    action:@selector(cancel:)];
-    self.navigationItem.leftBarButtonItem = cancelButton;
-    [cancelButton release];
-    
-    UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Save",@"from the hog name table")
-                                                                     style:UIBarButtonItemStyleDone
-                                                                    target:self
-                                                                    action:@selector(save:)];
-    self.navigationItem.rightBarButtonItem = saveButton;
-    [saveButton release];
-}
-
-// the textfield has been modified, check for empty strings and restore original navigation bar
--(void) textFieldDidEndEditing:(UITextField *)aTextField{
-    if ([textFieldBeingEdited.text length] == 0) 
-        textFieldBeingEdited.text = [NSString stringWithFormat:@"hedgehog %d",textFieldBeingEdited.tag];
-
-    self.textFieldBeingEdited = nil;
-    self.navigationItem.rightBarButtonItem = self.navigationItem.backBarButtonItem;
-    self.navigationItem.leftBarButtonItem = nil;
-}
-
-// limit the size of the field to 64 characters like in original frontend
--(BOOL) textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
-    int limit = 64;
-    return !([textField.text length] > limit && [string length] > range.length);
-}
-
-
 #pragma mark -
 #pragma mark View lifecycle
 -(void) viewDidLoad {
@@ -121,23 +69,23 @@
     // listen if any childController modifies the plist and write it if needed
     [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setWriteNeeded) name:@"setWriteNeedTeams" object:nil];
     isWriteNeeded = NO;
+    
+    self.title = NSLocalizedString(@"Edit team settings",@"");
 }
 
 -(void) viewWillAppear:(BOOL)animated {
     [super viewWillAppear:animated];
     
-    // load data about the team and write if there has been a change
+    // load data about the team and write if there has been a change from other childControllers
     if (isWriteNeeded) 
         [self writeFile];
     
-    NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.title];
+    NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.teamName];
     NSMutableDictionary *teamDict = [[NSMutableDictionary alloc] initWithContentsOfFile:teamFile];
     self.teamDictionary = teamDict;
     [teamDict release];
     [teamFile release];
-    
-    self.teamName = self.title;
-    
+        
     [self.tableView reloadData];
 }
 
@@ -145,13 +93,8 @@
 -(void) viewWillDisappear:(BOOL)animated {
     [super viewWillDisappear:animated];
 
-    // end the editing of the current field
-    if (textFieldBeingEdited != nil) {
-        [self save:nil];
-    }
-    
     if (isWriteNeeded) 
-        [self writeFile];        
+        [self writeFile];
 }
 
 #pragma mark -
@@ -161,22 +104,12 @@
 }
 
 -(void) writeFile {
-    NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.title];
+    NSString *teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),self.teamName];
+    [self.teamDictionary writeToFile:teamFile atomically:YES];
+    [teamFile release];
 
-    NSString *newTeamName = [self.teamDictionary objectForKey:@"teamname"];
-    if (![newTeamName isEqualToString:self.teamName]) {
-        //delete old
-        [[NSFileManager defaultManager] removeItemAtPath:teamFile error:NULL];
-        [teamFile release];
-        self.title = newTeamName;
-        self.teamName = newTeamName;
-        teamFile = [[NSString alloc] initWithFormat:@"%@/%@.plist",TEAMS_DIRECTORY(),newTeamName];
-    }
-    
-    [self.teamDictionary writeToFile:teamFile atomically:YES];
-    NSLog(@"writing: %@",teamDictionary);
+    DLog(@"%@",teamDictionary);
     isWriteNeeded = NO;
-    [teamFile release];
 }
 
 #pragma mark -
@@ -203,6 +136,25 @@
     return rows;
 }
 
+-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
+    NSString *sectionTitle = nil;
+    switch (section) {
+        case 0:
+            sectionTitle = NSLocalizedString(@"Team Name", @"");
+            break;
+        case 1:
+            sectionTitle = NSLocalizedString(@"Names and Hats", @"");
+            break;
+        case 2:
+            sectionTitle = NSLocalizedString(@"Team Preferences", @"");
+            break;
+        default:
+            DLog(@"Nope");
+            break;
+    }
+    return sectionTitle;
+}
+
 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
     static NSString *CellIdentifier0 = @"Cell0";
     static NSString *CellIdentifier1 = @"Cell1";
@@ -210,79 +162,48 @@
     
     NSArray *hogArray;
     UITableViewCell *cell = nil;
+    EditableCellView *editableCell = nil;
     NSInteger row = [indexPath row];
     UIImage *accessoryImage;
     
     switch ([indexPath section]) {
         case 0:
-            cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier0];
-            if (cell == nil) {
-                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
+            editableCell = (EditableCellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier0];
+            if (editableCell == nil) {
+                editableCell = [[[EditableCellView alloc] initWithStyle:UITableViewCellStyleDefault 
                                                reuseIdentifier:CellIdentifier0] autorelease];
-                // create a uitextfield for each row, expand it to take the maximum size
-                UITextField *aTextField = [[UITextField alloc] 
-                                           initWithFrame:CGRectMake(5, 12, (cell.frame.size.width + cell.frame.size.width/3) - 42, 25)];
-                aTextField.clearsOnBeginEditing = NO;
-                aTextField.returnKeyType = UIReturnKeyDone;
-                aTextField.adjustsFontSizeToFitWidth = YES;
-                aTextField.delegate = self;
-                aTextField.tag = [indexPath row];
-                aTextField.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2];
-                aTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
-                [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit];
-                [cell.contentView addSubview:aTextField];
-                [aTextField release];
+                editableCell.delegate = self;
+                editableCell.tag = TEAMNAME_TAG;
             }
             
-            cell.imageView.image = nil;
-            cell.accessoryType = UITableViewCellAccessoryNone;
-            for (UIView *oneView in cell.contentView.subviews) {
-                if ([oneView isMemberOfClass:[UITextField class]]) {
-                    // we find the uitextfied and we'll use its tag to understand which one is being edited
-                    UITextField *textFieldFound = (UITextField *)oneView;
-                    textFieldFound.text = [self.teamDictionary objectForKey:@"teamname"];
-                    textFieldFound.tag = TEAMNAME_TAG;
-                }
-            }            
+            editableCell.imageView.image = nil;
+            editableCell.accessoryType = UITableViewCellAccessoryNone;
+            editableCell.textField.text = self.teamName;
+
+            cell = editableCell;
             break;
         case 1:
-            cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
-            if (cell == nil) {
-                cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
+            editableCell = (EditableCellView *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier1];
+            if (editableCell == nil) {
+                editableCell = [[[EditableCellView alloc] initWithStyle:UITableViewCellStyleDefault 
                                                reuseIdentifier:CellIdentifier1] autorelease];
-                
-                // create a uitextfield for each row, expand it to take the maximum size
-                UITextField *aTextField = [[UITextField alloc] 
-                                           initWithFrame:CGRectMake(42, 12, (cell.frame.size.width + cell.frame.size.width/3) - 42, 25)];
-                aTextField.clearsOnBeginEditing = NO;
-                aTextField.returnKeyType = UIReturnKeyDone;
-                aTextField.adjustsFontSizeToFitWidth = YES;
-                aTextField.delegate = self;
-                aTextField.tag = [indexPath row];
-                aTextField.font = [UIFont boldSystemFontOfSize:[UIFont systemFontSize] + 2];
-                aTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
-                [aTextField addTarget:self action:@selector(save:) forControlEvents:UIControlEventEditingDidEndOnExit];
-                [cell.contentView addSubview:aTextField];
-                [aTextField release];
+                editableCell.delegate = self;
+                editableCell.tag = [indexPath row];
             }
             
             hogArray = [self.teamDictionary objectForKey:@"hedgehogs"];
             
+            // draw the hat on top of the hog
             NSString *hatFile = [[NSString alloc] initWithFormat:@"%@/%@.png", HATS_DIRECTORY(), [[hogArray objectAtIndex:row] objectForKey:@"hat"]];
             UIImage *hatSprite = [[UIImage alloc] initWithContentsOfFile: hatFile andCutAt:CGRectMake(0, 0, 32, 32)];
             [hatFile release];
-            cell.imageView.image = [self.normalHogSprite mergeWith:hatSprite atPoint:CGPointMake(0, -5)];
+            editableCell.imageView.image = [self.normalHogSprite mergeWith:hatSprite atPoint:CGPointMake(0, -5)];
             [hatSprite release];
-                        
-            for (UIView *oneView in cell.contentView.subviews) {
-                if ([oneView isMemberOfClass:[UITextField class]]) {
-                    // we find the uitextfied and we'll use its tag to understand which one is being edited
-                    UITextField *textFieldFound = (UITextField *)oneView;
-                    textFieldFound.text = [[hogArray objectAtIndex:row] objectForKey:@"hogname"];
-                }
-            }
             
-            cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
+            editableCell.textField.text = [[hogArray objectAtIndex:row] objectForKey:@"hogname"];
+            editableCell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
+            
+            cell = editableCell;
             break;
         case 2:
             cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier2];
@@ -339,7 +260,6 @@
     NSInteger row = [indexPath row];
     NSInteger section = [indexPath section];
     UITableViewController *nextController = nil;
-    UITableViewCell *cell;
     
     if (2 == section) {
         switch (row) {
@@ -380,20 +300,15 @@
         [self.navigationController pushViewController:nextController animated:YES];
         [nextController release];
     } else {
-        cell = [aTableView cellForRowAtIndexPath:indexPath];
-        for (UIView *oneView in cell.contentView.subviews) {
-            if ([oneView isMemberOfClass:[UITextField class]]) {
-                textFieldBeingEdited = (UITextField *)oneView;
-                [textFieldBeingEdited becomeFirstResponder];
-            }
-        }
+        EditableCellView *cell = (EditableCellView *)[aTableView cellForRowAtIndexPath:indexPath];
+        [cell replyKeyboard];
         [aTableView deselectRowAtIndexPath:indexPath animated:NO];
     }
 
 }
 
 // action to perform when you want to change a hog hat
--(void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
+-(void) tableView:(UITableView *)aTableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
     if (nil == hogHatViewController) {
         hogHatViewController = [[HogHatViewController alloc] initWithStyle:UITableViewStyleGrouped];
     }
@@ -402,6 +317,10 @@
     hogHatViewController.teamDictionary = self.teamDictionary;
     hogHatViewController.selectedHog = [indexPath row];
     
+    // if we are editing the field undo any change before proceeding
+    EditableCellView *cell = (EditableCellView *)[aTableView cellForRowAtIndexPath:indexPath];
+    [cell cancel:nil];
+    
     [self.navigationController pushViewController:hogHatViewController animated:YES];
 }
 
@@ -409,9 +328,7 @@
 #pragma mark -
 #pragma mark Memory management
 -(void) didReceiveMemoryWarning {
-    // Releases the view if it doesn't have a superview.
     [super didReceiveMemoryWarning];
-    // Relinquish ownership any cached data, images, etc that aren't in use.
     if (hogHatViewController.view.superview == nil)
         hogHatViewController = nil;
     if (gravesViewController.view.superview == nil)
@@ -424,11 +341,11 @@
         flagsViewController = nil;
     if (levelViewController.view.superview == nil)
         levelViewController = nil;
+    MSG_MEMCLEAN();
 }
 
 -(void) viewDidUnload {
     self.teamDictionary = nil;
-    self.textFieldBeingEdited = nil;
     self.teamName = nil;
     self.normalHogSprite = nil;
     self.secondaryItems = nil;
@@ -443,7 +360,6 @@
 
 -(void) dealloc {
     [teamDictionary release];
-    [textFieldBeingEdited release];
     [teamName release];
     [normalHogSprite release];
     [secondaryItems release];
--- a/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/SingleWeaponViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -226,7 +226,7 @@
 #pragma mark -
 #pragma mark editableCellView delegate
 // set the new value
--(void) saveTextFieldValue:(NSString *)textString {    
+-(void) saveTextFieldValue:(NSString *)textString withTag:(NSInteger) tagValue {    
     // delete old file
     [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@.plist",WEAPONS_DIRECTORY(),self.weaponName] error:NULL];
     // update filename
--- a/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m	Tue Jul 20 03:14:43 2010 +0200
+++ b/project_files/HedgewarsMobile/Classes/TeamSettingsViewController.m	Tue Jul 20 05:37:58 2010 +0200
@@ -132,7 +132,7 @@
     NSString *selectedTeamFile = [listOfTeams objectAtIndex:row];
     
     // this must be set so childController can load the correct plist
-    childController.title = [selectedTeamFile stringByDeletingPathExtension];
+    childController.teamName = [selectedTeamFile stringByDeletingPathExtension];
     [childController.tableView setContentOffset:CGPointMake(0,0) animated:NO];
 
     [self.navigationController pushViewController:childController animated:YES];