From 72c8aa056cd8cc23d1f8e22db6e270d5bd2aaa8e Mon Sep 17 00:00:00 2001
From: Maxime Graulich <maxime.graulich@gmail.com>
Date: Thu, 8 Aug 2013 13:04:17 +0000
Subject: [PATCH] Fix parameters on iOS

---
 .../mobile/iOS/Onelab/DetailViewController.h  |   2 +
 .../mobile/iOS/Onelab/DetailViewController.mm |   5 +-
 .../mobile/iOS/Onelab/MasterViewController.h  |   4 +-
 .../mobile/iOS/Onelab/MasterViewController.mm | 381 ++++--------------
 contrib/mobile/iOS/Onelab/parameter.h         |  73 ++++
 contrib/mobile/iOS/Onelab/parameter.mm        | 330 +++++++++++++++
 6 files changed, 497 insertions(+), 298 deletions(-)
 create mode 100644 contrib/mobile/iOS/Onelab/parameter.h
 create mode 100644 contrib/mobile/iOS/Onelab/parameter.mm

diff --git a/contrib/mobile/iOS/Onelab/DetailViewController.h b/contrib/mobile/iOS/Onelab/DetailViewController.h
index 2c6721f19b..13e9c2188c 100644
--- a/contrib/mobile/iOS/Onelab/DetailViewController.h
+++ b/contrib/mobile/iOS/Onelab/DetailViewController.h
@@ -27,4 +27,6 @@
 
 @property (weak, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
 
+@property (nonatomic, retain) NSString *initialModel;
+
 @end
diff --git a/contrib/mobile/iOS/Onelab/DetailViewController.mm b/contrib/mobile/iOS/Onelab/DetailViewController.mm
index 6ad70a7fd6..87eeef2722 100644
--- a/contrib/mobile/iOS/Onelab/DetailViewController.mm
+++ b/contrib/mobile/iOS/Onelab/DetailViewController.mm
@@ -55,6 +55,7 @@
     [self configureView];
     scaleFactor = 1.;
     setObjCBridge((__bridge void*) self);
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(requestRender) name:@"requestRender" object:nil];
     if(![[UIDevice currentDevice].model isEqualToString:@"iPad"] && ![[UIDevice currentDevice].model isEqualToString:@"iPad Simulator"]){
         UIBarButtonItem *settings = [[UIBarButtonItem alloc] initWithTitle:@"Settings" style:UIBarButtonItemStyleBordered target:self action:@selector(showSettings)];
         UIBarButtonItem *postpro = [[UIBarButtonItem alloc] initWithTitle:@"Post processing" style:UIBarButtonItemStyleBordered target:self action:@selector(showPostpro)];
@@ -117,7 +118,7 @@
     sender.numberOfTapsRequired = 2;
     if(sender.state == UIGestureRecognizerStateEnded){
         scaleFactor = 1;
-        glView->mContext->eventHandler(5);
+        glView->mContext->eventHandler(10);
         [glView drawView];
     }
 }
@@ -352,7 +353,7 @@ void messageFromCpp (void *self, std::string level, std::string msg)
 {
     if(level == "RequestRender"){
         [(__bridge id)self requestRender];
-        //[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshParameters" object:nil];
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"refreshParameters" object:nil];
     }
     else if(level == "Error")
         ;//[(__bridge id)self showAlert:msg title:level];
diff --git a/contrib/mobile/iOS/Onelab/MasterViewController.h b/contrib/mobile/iOS/Onelab/MasterViewController.h
index c6be3b2533..5481562a88 100644
--- a/contrib/mobile/iOS/Onelab/MasterViewController.h
+++ b/contrib/mobile/iOS/Onelab/MasterViewController.h
@@ -11,7 +11,7 @@
 
 @class DetailViewController;
 
-@interface MasterViewController : UITableViewController <UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate>
+@interface MasterViewController : UITableViewController
 {
     @private
     NSMutableArray *_sections;
@@ -23,4 +23,6 @@
 
 @property (strong, nonatomic) DetailViewController *detailViewController;
 
+- (void)resetParameters:(id)sender;
+
 @end
diff --git a/contrib/mobile/iOS/Onelab/MasterViewController.mm b/contrib/mobile/iOS/Onelab/MasterViewController.mm
index 2bf97da4ef..3ff7ab075e 100644
--- a/contrib/mobile/iOS/Onelab/MasterViewController.mm
+++ b/contrib/mobile/iOS/Onelab/MasterViewController.mm
@@ -7,8 +7,8 @@
 //
 
 #import "MasterViewController.h"
-
 #import "DetailViewController.h"
+#import "parameter.h"
 
 @interface MasterViewController () {
 
@@ -28,19 +28,45 @@
 {
     [super viewDidLoad];
 	// Do any additional setup after loading the view, typically from a nib.
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshObject:) name:@"refreshParameters" object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshParameters:) name:@"refreshParameters" object:nil];
     runButton = [[UIBarButtonItem alloc] initWithTitle:@"Run" style:UIBarButtonItemStyleBordered target:self action:@selector(runWithNewParameter)];
     [runButton setTitle:@"Run"];
     self.navigationItem.leftBarButtonItem = runButton;
 
-    UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refreshObject:)];
-    self.navigationItem.rightBarButtonItem = addButton;
+    UIBarButtonItem *refresh = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(resetParameters:)];
+    self.navigationItem.rightBarButtonItem = refresh;
     self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
     
     _sections = [[NSMutableArray alloc] init];
     _sectionstitle = [[NSMutableArray alloc] init];
 }
 
+- (void) addParameterNumber:(onelab::number)p inSection:(NSMutableArray*)section
+{
+    if(p.getChoices().size() && p.getChoices().size() == p.getValueLabels().size()) { // enumeration
+        parameterNumberList *param = [[parameterNumberList alloc] initWithNumber:p];
+        [section addObject:param];
+    }
+    else if(p.getChoices().size() == 2 && p.getChoices()[0] == 0 && p.getChoices()[1] == 1) { // check box
+        parameterNumberCheckbox *param = [[parameterNumberCheckbox alloc] initWithNumber:p];
+        [section addObject:param];
+    }
+    else if(p.getStep() == 0) { // text box
+        parameterNumberTextbox *param = [[parameterNumberTextbox alloc] initWithNumber:p];
+        [section addObject:param];
+    }
+    else
+    {
+        parameterNumberRange *param = [[parameterNumberRange alloc] initWithNumber:p];
+        [section addObject:param];
+    }
+}
+- (void) addParameterString:(onelab::string)p inSection:(NSMutableArray*)section
+{
+    parameterStringList *param = [[parameterStringList alloc] initWithString:p];
+    [section addObject:param];
+}
+
 - (void) getAvailableParam
 {
     std::vector<onelab::number> number;
@@ -49,34 +75,29 @@
     {
         if(!number[i].getVisible()) continue;
         NSString *name=[NSString stringWithCString:number[i].getName().c_str() encoding:[NSString defaultCStringEncoding]];
-        NSArray *splitedname = [name componentsSeparatedByString:@"/"];
-        NSString * sectiontitle = [splitedname objectAtIndex:0];
+        NSString * sectiontitle = [[name componentsSeparatedByString:@"/"] objectAtIndex:0];
         bool found = false;
         
         for(int j=0;j<[_sectionstitle count];j++)
         {
             NSString *title = [_sectionstitle objectAtIndex:j];
-            if([title isEqualToString:@"Post proccessing"])
-            {
-                [_sections removeObjectAtIndex:j];
-                [_sectionstitle removeObjectAtIndex:j];
-            }
             if([title isEqualToString:sectiontitle]) // the section already exists
             {
                 NSMutableArray *section = [_sections objectAtIndex:j];
                 for(int k=0; k<[section count];k++)
-                    if([[section objectAtIndex: k] isEqualToString:name]){found = true; break;}
+                    if([[(parameter*)[section objectAtIndex: k] getName] isEqualToString:name]){found = true; break;}
                 if(!found)
-                    [section addObject:name];
+                    [self addParameterNumber:number[i] inSection:section];
                 found = true;
                 break;
             }
         }
         if(found) continue;
         // we have to create the section
-        NSMutableArray *newSection = [[NSMutableArray alloc] initWithObjects:name, nil];
+        NSMutableArray *newSection = [[NSMutableArray alloc] init];
         [_sections addObject:newSection];
         [_sectionstitle addObject:sectiontitle];
+        [self addParameterNumber:number[i] inSection:[_sections lastObject]];
     }
     std::vector<onelab::string> string;
     onelab::server::instance()->get(string);
@@ -85,8 +106,7 @@
         if(!string[i].getVisible()) continue;
         if(string[i].getKind() == "file") continue;
         NSString *name=[NSString stringWithCString:string[i].getName().c_str() encoding:[NSString defaultCStringEncoding]];
-        NSArray *splitedname = [name componentsSeparatedByString:@"/"];
-        NSString * sectiontitle = [splitedname objectAtIndex:0];
+        NSString * sectiontitle = [[name componentsSeparatedByString:@"/"] objectAtIndex:0];
         bool found = false;
         
         for(int j=0;j<[_sectionstitle count];j++)
@@ -96,18 +116,19 @@
             {
                 NSMutableArray *section = [_sections objectAtIndex:j];
                 for(int k=0; k<[section count];k++)
-                    if([[section objectAtIndex: k] isEqualToString:name]){found = true; break;} // the parameters is already in the section
+                    if([[(parameter*)[section objectAtIndex: k] getName] isEqualToString:name]){found = true; break;} // the parameters is already in the section
                 if(!found)
-                    [section addObject:name];
+                    [self addParameterString:string[i] inSection:section];
                 found = true;
                 break;
             }
         }
         if(found) continue;
         // we have to create the section
-        NSMutableArray *newSection = [[NSMutableArray alloc] initWithObjects:name, nil];
+        NSMutableArray *newSection = [[NSMutableArray alloc] init];
         [_sections addObject:newSection];
         [_sectionstitle addObject:sectiontitle];
+        [self addParameterString:string[i] inSection:[_sections lastObject]];
     }
 }
 
@@ -128,64 +149,20 @@
 {
     return YES;
 }
-
-- (void)refreshObject:(id)sender
+- (void)refreshParameters:(id)sender
+{
+    [self getAvailableParam]; // Get the param
+    [self.tableView reloadData];
+}
+- (void)resetParameters:(id)sender
 {
     onelab_cb("reset");
     [_sections removeAllObjects];
     [_sectionstitle removeAllObjects];
+    [self.tableView reloadData];
     [self getAvailableParam]; // Get the param
-    for(int i=0; i<_sections.count;i++) // Refresh they values
-    {
-        NSMutableArray *mSection = [_sections objectAtIndex:i];
-        for(int n=0; n <mSection.count;n++)
-        {
-            NSString *paramName = [mSection objectAtIndex:n];
-            
-            std::vector<onelab::number> number;
-            onelab::server::instance()->get(number,[paramName UTF8String]);
-            if(number.size() > 0){
-                UITableViewCell *cell = [self.tableView cellForRowAtIndexPath: [NSIndexPath indexPathForRow:n inSection:i]];
-                for(UIView *v in cell.subviews)
-                {
-                    if ([v isKindOfClass:UISlider.class]){
-                        UISlider *slider = (UISlider*)v;
-                        [slider setValue:number[0].getValue()];
-                        break;
-                    }
-                    else if([v isKindOfClass:UIPickerView.class]){
-                        UIView *picker = (UISlider*)v;
-                        [(UIPickerView *)picker reloadAllComponents];
-                        int index=0;
-                        for(int i=0;i<number[0].getChoices().size();i++)
-                            if(number[0].getChoices()[i] == number[0].getValue()){index = i; break;}
-                        [(UIPickerView *)picker selectRow:index inComponent:0 animated:YES];
-                        break;
-                    }
-                    else if([v isKindOfClass:UITextField.class])
-                    {
-                        UITextField *text = (UITextField*) v;
-                        [text setText:[NSString stringWithFormat:@"%f", number[0].getValue()]];
-                        break;
-                    }
-                }
-            }
-            std::vector<onelab::string> string;
-            onelab::server::instance()->get(string,[paramName UTF8String]);
-            if(string.size() > 0) {
-                UIView *picker = [self.tableView viewWithTag:(1000*i+n)];
-                if([picker isKindOfClass:UIPickerView.class]){
-                    [(UIPickerView *)picker reloadAllComponents];
-                    int index = -1;
-                    for(int i=0;i<string[0].getChoices().size();i++)
-                        if(string[0].getChoices()[i] == string[0].getValue()){index = i; break;}
-                    if(index >= 0)
-                        [(UIPickerView *)picker selectRow:index inComponent:0 animated:YES];
-                     }
-            }
-        }
-    }
     [self.tableView reloadData];
+    onelab_cb("check");
     [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
 }
 
@@ -193,13 +170,15 @@
 {
     dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // TODO fix Run/Stop for iPhone
         [runButton setTitle:@"Stop"];
-        [self refreshControl];
+        [self.view setNeedsDisplay];
         [runButton setAction:@selector(stopRunning)];
+        self.navigationItem.rightBarButtonItem.enabled = NO;
         onelab_cb("compute");
         [runButton setTitle:@"Run"];
-        [self refreshControl];
+        [self.view setNeedsDisplay];
         [runButton setAction:@selector(runWithNewParameter)];
-        [self getAvailableParam];
+        self.navigationItem.rightBarButtonItem.enabled = YES;
+        //[[NSNotificationCenter defaultCenter] postNotificationName:@"refreshParameters" object:nil];
     });
     if(![[UIDevice currentDevice].model isEqualToString:@"iPad"] && ![[UIDevice currentDevice].model isEqualToString:@"iPad Simulator"])
         [self.navigationController popViewControllerAnimated:YES];
@@ -234,242 +213,54 @@
 {
     // get the param with his name
     NSMutableArray *sectionContent = [_sections objectAtIndex:[indexPath section]];
-    NSString *paramName = [sectionContent objectAtIndex:[indexPath row]];
-    std::vector<onelab::number> number;
-    std::vector<onelab::string> string;
+    parameter *tmp = [sectionContent objectAtIndex:[indexPath row]];
     
-    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:paramName];
+    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
     if(cell == nil)
-        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:paramName];
+        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:[[tmp getLabel] text]];
     else
         return cell;
-    onelab::server::instance()->get(number,[paramName UTF8String]);
-    onelab::server::instance()->get(string,[paramName UTF8String]);
-    if(number.size() > 0)
-    {
-        UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-        if(number[0].getReadOnly())
-        {
-            [cell setUserInteractionEnabled:NO];
-            lbl.alpha = 0.439216f;
-        }
-        if(number[0].getLabel() != "")
-            [lbl setText:[NSString stringWithCString:number[0].getLabel().c_str()  encoding:[NSString defaultCStringEncoding]]];
-        else
-            [lbl setText:[NSString stringWithCString:number[0].getName().c_str()  encoding:[NSString defaultCStringEncoding]]];
-        
-        [lbl setBackgroundColor:[UIColor clearColor]];
-        lbl.tag = -(1000 * indexPath.section + indexPath.row);
-        [cell addSubview:lbl];
-        if(number[0].getChoices().size() && number[0].getChoices().size() == number[0].getValueLabels().size()) // enumeration
-        {
-            UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-            
-            picker.showsSelectionIndicator = YES;
-            picker.tag = 1000 * indexPath.section + indexPath.row;
-            [picker setDataSource:self];
-            [picker setDelegate:self];
-            for(int row=0;row<number[0].getChoices().size();row++)
-                if(number[0].getValue() == number[0].getChoices()[row])[picker selectRow:row inComponent:0 animated:NO];
-            [cell addSubview:picker];
-        }
-        else if(number[0].getChoices().size() == 2 && number[0].getChoices()[0] == 0 && number[0].getChoices()[1] == 1) // check box
-        {
-            UISwitch *swtch = [[UISwitch alloc] initWithFrame:CGRectMake(10, 5, cell.frame.size.width - 40, cell.frame.size.height)];
-            lbl.tag = 1000 * indexPath.section + indexPath.row;
-            [swtch setSelected:(number[0].getValue() == 1)];
-            [lbl setFrame:CGRectMake(100, 5, cell.frame.size.width - 110, cell.frame.size.height)];
-            [cell addSubview:swtch];
-            
-        }
-        else if(number[0].getStep() == 0) // text box
-        {
-            UITextField *textfield = [[UITextField alloc] initWithFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-            textfield.tag = 1000 * indexPath.section + indexPath.row;
-            [textfield setBorderStyle:UITextBorderStyleRoundedRect];
-            [textfield setText:[NSString stringWithFormat:@"%f",number[0].getValue()]];
-            [textfield setKeyboardType:UIKeyboardTypeNumberPad];
-            [textfield addTarget:self action:@selector(PViewNbIso:) forControlEvents:UIControlEventValueChanged];
-            [textfield setDelegate:self];
-            [cell addSubview:textfield];
-        }
-        else // slider with range
-        {
-            UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-            slider.tag = 1000 * indexPath.section + indexPath.row;
-            [slider setMaximumValue:number[0].getMax()];
-            [slider setMinimumValue:number[0].getMin()];
-            [slider setValue:number[0].getValue()];
-            //TODO add step ?
-            [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventTouchUpOutside];
-            [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventTouchUpInside];
-            [lbl setText:[NSString stringWithFormat:@"%@ %f" ,[NSString stringWithCString:number[0].getLabel().c_str()  encoding:[NSString defaultCStringEncoding]], number[0].getValue()]];
-            [cell addSubview:slider];
-        }
-        
+    [cell setUserInteractionEnabled:!([tmp isReadOnly])];
+    [tmp setLabelFrame:CGRectMake(20, 5, cell.frame.size.width - 40, cell.frame.size.height/2)];
+    [cell addSubview:[tmp getLabel]];
+    if([tmp isKindOfClass:[parameterStringList class]]) {
+        parameterStringList *param = (parameterStringList *)tmp;
+        [param setFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
+        [cell addSubview:[param getList]];
     }
-    else if(string.size() > 0)
-    {
-        UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(20, 5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-        if(string[0].getReadOnly())
-        {
-            [cell setUserInteractionEnabled:NO];
-            lbl.alpha = 0.439216f;
-        }
-        [lbl setText:[NSString stringWithCString:string[0].getLabel().c_str() encoding:[NSString defaultCStringEncoding]]];
-        [lbl setBackgroundColor:[UIColor clearColor]];
-        lbl.tag = -(1000 * indexPath.section + indexPath.row);
-        UIPickerView *picker = [[UIPickerView alloc] initWithFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
-        picker.showsSelectionIndicator = YES;
-        picker.tag = 1000 * indexPath.section + indexPath.row;
-        [picker setDataSource:self];
-        [picker setDelegate:self];
-        for(int row=0;row<string[0].getChoices().size();row++)
-            if(string[0].getValue() == string[0].getChoices()[row])[picker selectRow:row inComponent:0 animated:NO];
-        [cell addSubview:picker];
-        [cell addSubview:lbl];
+    else if([tmp isKindOfClass:[parameterNumberList class]]) {
+        parameterNumberList *param = (parameterNumberList *)tmp;
+        [param setFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
+        [cell addSubview:[param getList]];
+    }
+    else if([tmp isKindOfClass:[parameterNumberCheckbox class]]) {
+        parameterNumberCheckbox *param = (parameterNumberCheckbox *)tmp;
+        [param setLabelFrame:CGRectMake(100, 5, cell.frame.size.width - 110, cell.frame.size.height)];
+        [param setFrame:CGRectMake(10, 5, cell.frame.size.width - 40, cell.frame.size.height)];
+        [cell addSubview:[param getCheckbox]];
+    }
+    else if([tmp isKindOfClass:[parameterNumberRange class]]) {
+        parameterNumberRange *param = (parameterNumberRange *)tmp;
+        [param setFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
+        [cell addSubview:[param getSlider]];
     }
+    else if([tmp isKindOfClass:[parameterNumberTextbox class]]) {
+        parameterNumberTextbox *param = (parameterNumberTextbox *)tmp;
+        [param setFrame:CGRectMake(20, cell.frame.size.height/2+5, cell.frame.size.width - 40, cell.frame.size.height/2)];
+        [cell addSubview:[param getTextbox]];
+    }
+        
     return cell;
 }
 
 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 {
-    NSString *paramName = [[_sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
-    
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(number,[paramName UTF8String]);
-    if(number.size() > 0){
-        if(number[0].getChoices().size() && number[0].getChoices().size() == number[0].getValueLabels().size()) // enumeration
-            return 200.f;
-        if(number[0].getChoices().size() == 2 && number[0].getChoices()[0] == 0 && number[0].getChoices()[1] == 1) // check box
-            return 40.f;
-        return 60.f;
-    }
-    std::vector<onelab::string> string;
-    onelab::server::instance()->get(string,[paramName UTF8String]);
-    if(string.size() > 0) return 200.f;
-    return 50.f;
+    parameter *param = [[_sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
+    return [[param class] getHeight];
 }
 
 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
 {
     return [_sectionstitle objectAtIndex:section];
 }
-
--(void)sliderValueChanged:(UISlider *)sender
-{
-    int nsection = (int)(sender.tag/1000), nrow = sender.tag%1000;
-    NSString *title = [[_sections objectAtIndex:nsection] objectAtIndex:nrow];
-        
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(number,[title UTF8String]);
-    number[0].setValue(sender.value);
-    onelab::server::instance()->set(number[0]);
-    UITableViewCell *cell = [self.tableView cellForRowAtIndexPath: [NSIndexPath indexPathForRow:nrow inSection:nsection]];
-    UILabel *lbl = nil;
-    for(UIView *v in cell.subviews)
-        if ([v isKindOfClass:UILabel.class]){
-            lbl = (UILabel*)v;
-            break;
-        }
-    if(lbl != nil)
-        [lbl setText:[NSString stringWithFormat:@"%s %f" ,number[0].getLabel().c_str(), sender.value]];
-    if(onelab_cb("check") == 1)
-        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
-}
-
-#pragma mark - pickerView
-
--(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
-{
-    int nsection = (int)(pickerView.tag/1000), nrow = pickerView.tag%1000;
-    NSString *title = [[_sections objectAtIndex:nsection] objectAtIndex:nrow];
-    
-    std::vector<onelab::string> string;
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(string,[title UTF8String]);
-    onelab::server::instance()->get(number,[title UTF8String]);
-
-    if(string.size() > 0) return string[0].getChoices().size();
-    else if(number.size() > 0) return number[0].getChoices().size();
-    else return 0;
-}
--(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
-{
-    int nsection = (int)(pickerView.tag/1000), nrow = pickerView.tag%1000;
-    NSString *title = [[_sections objectAtIndex:nsection] objectAtIndex:nrow];
-    
-    std::vector<onelab::string> string;
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(string,[title UTF8String]);
-    onelab::server::instance()->get(number,[title UTF8String]);
-    
-    if(string.size() > 0)
-    {
-        return [NSString stringWithCString:string[0].getChoices()[row].c_str() encoding:[NSString defaultCStringEncoding]];
-    }
-    else if(number.size() > 0) return [NSString stringWithCString:number[0].getValueLabel(number[0].getChoices()[row]).c_str() encoding:[NSString defaultCStringEncoding]];
-    else return @"?";
-}
--(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
-{
-    return 1;
-}
--(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
-{
-    int nsection = (int)(pickerView.tag/1000), nrow = pickerView.tag%1000;
-    NSString *title = [[_sections objectAtIndex:nsection] objectAtIndex:nrow];
-    
-    std::vector<onelab::string> string;
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(string,[title UTF8String]);
-    onelab::server::instance()->get(number,[title UTF8String]);
-
-    int index = [pickerView selectedRowInComponent:0];
-    if(string.size() > 0)
-    {
-        std::string selected = string[0].getChoices()[index];
-        string[0].setValue(selected);
-        onelab::server::instance()->set(string[0]);
-    }
-    else if(number.size() > 0)
-    {
-        double selected = number[0].getChoices()[index];
-        number[0].setValue(selected);
-        onelab::server::instance()->set(number[0]);
-    }
-    if(onelab_cb("check") == 1)
-        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
-}
-
-#pragma mark - textfield
-
--(BOOL)textFieldShouldEndEditing:(UITextField *)textField
-{
-    int nsection = (int)(textField.tag/1000), nrow = textField.tag%1000;
-    NSString *title = [[_sections objectAtIndex:nsection] objectAtIndex:nrow];
-    
-    std::vector<onelab::string> string;
-    std::vector<onelab::number> number;
-    onelab::server::instance()->get(string,[title UTF8String]);
-    onelab::server::instance()->get(number,[title UTF8String]);
-    
-    if(number.size() > 0)
-    {
-        number[0].setValue([textField.text doubleValue]);
-        onelab::server::instance()->set(number[0]);
-    }
-    else if(string.size() > 0)
-    {
-        string[0].setValue([textField.text UTF8String]);
-        onelab::server::instance()->set(string[0]);
-    }
-    return YES;
-}
--(BOOL)textFieldShouldReturn:(UITextField *)textField
-{
-    [textField endEditing:YES];
-    return YES;
-}
-
 @end
diff --git a/contrib/mobile/iOS/Onelab/parameter.h b/contrib/mobile/iOS/Onelab/parameter.h
new file mode 100644
index 0000000000..3db4bf0032
--- /dev/null
+++ b/contrib/mobile/iOS/Onelab/parameter.h
@@ -0,0 +1,73 @@
+//
+//  parameter.h
+//  Onelab
+//
+//  Created by Maxime Graulich on 07/08/13.
+//  Copyright (c) 2013 Maxime Graulich. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <Gmsh/onelab.h>
+
+#import "drawContext.h"
+
+@interface parameter : NSObject
+{
+    @protected
+    NSString *name;
+    UILabel *label;
+}
+-(id)init;
+-(void)setFrame:(CGRect)frame;
+-(void)setLabelFrame:(CGRect)frame;
+-(NSString *)getName;
+-(UILabel *)getLabel;
+-(bool)isReadOnly;
++(double)getHeight;
+@end
+
+@interface parameterStringList : parameter <UIPickerViewDataSource, UIPickerViewDelegate>
+{
+    @protected
+    UIPickerView *picker;
+}
+-(id)initWithString:(onelab::string)string;
+-(UIPickerView *)getList;
+@end
+
+
+@interface parameterNumberList : parameter <UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate>
+{
+    @protected
+    UIPickerView *picker;
+}
+-(id)initWithNumber:(onelab::number)number;
+-(UIPickerView *)getList;
+@end
+
+@interface parameterNumberCheckbox : parameter
+{
+    @protected
+    UISwitch *checkbox;
+}
+-(id)initWithNumber:(onelab::number)number;
+-(UISwitch *)getCheckbox;
+@end
+
+@interface parameterNumberRange : parameter
+{
+    @protected
+    UISlider *slider;
+}
+-(id)initWithNumber:(onelab::number)number;
+-(UISlider *)getSlider;
+@end
+
+@interface parameterNumberTextbox : parameter <UITextFieldDelegate>
+{
+@protected
+    UITextField *textbox;
+}
+-(id)initWithNumber:(onelab::number)number;
+-(UITextField *)getTextbox;
+@end
diff --git a/contrib/mobile/iOS/Onelab/parameter.mm b/contrib/mobile/iOS/Onelab/parameter.mm
new file mode 100644
index 0000000000..6df5bb3dc3
--- /dev/null
+++ b/contrib/mobile/iOS/Onelab/parameter.mm
@@ -0,0 +1,330 @@
+//
+//  parameter.m
+//  Onelab
+//
+//  Created by Maxime Graulich on 07/08/13.
+//  Copyright (c) 2013 Maxime Graulich. All rights reserved.
+//
+
+#import "parameter.h"
+
+@implementation parameter
+-(id)init
+{
+    self = [super init];
+    if(self)
+    {
+        label = [[UILabel alloc] init];
+        [label setBackgroundColor:[UIColor clearColor]];
+    }
+    return self;
+}
+-(NSString *)getName
+{
+    return name;
+}
+-(UILabel *)getLabel
+{
+    return label;
+}
+-(void)setFrame:(CGRect)frame
+{
+    return;
+}
+-(void)setLabelFrame:(CGRect)frame
+{
+    [label setFrame:frame];
+}
+-(bool)isReadOnly
+{
+    return NO;
+}
++(double)getHeight
+{
+    return 60.0f;
+}
+@end
+
+@implementation parameterStringList
+-(id) initWithString:(onelab::string)string
+{
+    self = [super init];
+    if(self)
+    {
+        label.alpha = (string.getReadOnly())? 0.439216f : 1.0f;
+        [label setText:[NSString stringWithCString:(string.getLabel() != "")?string.getLabel().c_str():string.getName().c_str() encoding:[NSString defaultCStringEncoding]]];
+        name = [NSString stringWithCString:string.getName().c_str() encoding:[NSString defaultCStringEncoding]];
+        picker = [[UIPickerView alloc] init];
+        picker.showsSelectionIndicator = YES;
+        [picker setDataSource:self];
+        [picker setDelegate:self];
+        for(int row=0;row<string.getChoices().size();row++)
+            if(string.getValue() == string.getChoices()[row])[picker selectRow:row inComponent:0 animated:NO];
+    }
+    return self;
+}
+-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+    return 1;
+}
+-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+    std::vector<onelab::string> string;
+    onelab::server::instance()->get(string,[name UTF8String]);
+    if(string.size() < 1) return 0;
+    return string[0].getChoices().size();
+}
+-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+    std::vector<onelab::string> string;
+    onelab::server::instance()->get(string,[name UTF8String]);
+    if(string.size() < 1) return @"NULL";
+    return [NSString stringWithCString:string[0].getChoices()[row].c_str() encoding:[NSString defaultCStringEncoding]];
+}
+-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+    std::vector<onelab::string> string;
+    onelab::server::instance()->get(string,[name UTF8String]);
+    if(string.size() < 1) return;
+    std::string selected = string[0].getChoices()[row];
+    string[0].setValue(selected);
+    onelab::server::instance()->set(string[0]);
+    if(onelab_cb("check") == 1)
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
+}
+-(void)setFrame:(CGRect)frame
+{
+    [picker setFrame:frame];
+}
+-(UIPickerView *)getList
+{
+    return picker;
+}
+-(bool)isReadOnly
+{
+    std::vector<onelab::string> string;
+    onelab::server::instance()->get(string,[name UTF8String]);
+    if(string.size() < 1) return YES;
+    return string[0].getReadOnly();
+}
++(double)getHeight
+{
+    return 200.0f;
+}
+@end
+
+@implementation parameterNumberList
+-(id) initWithNumber:(onelab::number) number
+{
+    self = [super init];
+    if(self)
+    {
+        label.alpha = (number.getReadOnly())? 0.439216f : 1.0f;
+        [label setText:[NSString stringWithCString:(number.getLabel() != "")?number.getLabel().c_str():number.getName().c_str() encoding:[NSString defaultCStringEncoding]]];
+        name = [NSString stringWithCString:number.getName().c_str() encoding:[NSString defaultCStringEncoding]];
+        picker = [[UIPickerView alloc] init];
+        picker.showsSelectionIndicator = YES;
+        [picker setDataSource:self];
+        [picker setDelegate:self];
+        for(int row=0;row<number.getChoices().size();row++)
+            if(number.getValue() == number.getChoices()[row])[picker selectRow:row inComponent:0 animated:NO];
+    }
+    return self;
+}
+-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
+{
+    return 1;
+}
+-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return 0;
+    return number[0].getChoices().size();
+}
+-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return @"NULL";
+    return [NSString stringWithCString:number[0].getValueLabel(number[0].getChoices()[row]).c_str() encoding:[NSString defaultCStringEncoding]];
+}
+-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return;
+    double selected = number[0].getChoices()[row];
+    number[0].setValue(selected);
+    onelab::server::instance()->set(number[0]);
+    if(onelab_cb("check") == 1)
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
+}
+-(void)setFrame:(CGRect)frame
+{
+    [picker setFrame:frame];
+}
+-(UIPickerView *)getList
+{
+    return picker;
+}
+-(bool)isReadOnly
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return YES;
+    return number[0].getReadOnly();
+}
++(double)getHeight
+{
+    return 200.0f;
+}
+@end
+
+@implementation parameterNumberCheckbox
+-(id) initWithNumber:(onelab::number) number
+{
+    self = [super init];
+    if(self)
+    {
+        label.alpha = (number.getReadOnly())? 0.439216f : 1.0f;
+        [label setText:[NSString stringWithCString:(number.getLabel() != "")?number.getLabel().c_str():number.getName().c_str() encoding:[NSString defaultCStringEncoding]]];
+        name = [NSString stringWithCString:number.getName().c_str() encoding:[NSString defaultCStringEncoding]];
+        checkbox = [[UISwitch alloc] init];
+        [checkbox setSelected:(number.getValue() == 1)];
+        [checkbox addTarget:self action:@selector(valueChange:) forControlEvents:UIControlEventValueChanged];
+    }
+    return self;
+}
+-(void) valueChange:(UISwitch *)sender
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return;
+    number[0].setValue(([sender isOn])? 1 : 0);
+    onelab::server::instance()->set(number[0]);
+    if(onelab_cb("check") == 1)
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
+}
+-(void)setFrame:(CGRect)frame
+{
+    [checkbox setFrame:frame];
+}
+-(UISwitch *)getCheckbox
+{
+    return checkbox;
+}
+-(bool)isReadOnly
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return YES;
+    return number[0].getReadOnly();
+}
++(double)getHeight
+{
+    return 40.0f;
+}
+@end
+
+@implementation parameterNumberRange
+-(id) initWithNumber:(onelab::number) number
+{
+    self = [super init];
+    if(self)
+    {
+        label.alpha = (number.getReadOnly())? 0.439216f : 1.0f;
+        name = [NSString stringWithCString:number.getName().c_str() encoding:[NSString defaultCStringEncoding]];
+        slider = [[UISlider alloc] init];
+        [slider setMaximumValue:number.getMax()];
+        [slider setMinimumValue:number.getMin()];
+        [slider setValue:number.getValue()];
+        //TODO add step ?
+        [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventTouchUpOutside];
+        [slider addTarget:self action:@selector(sliderValueChanged:) forControlEvents:UIControlEventTouchUpInside];
+        [label setText:[NSString stringWithFormat:@"%@ %f" ,[NSString stringWithCString:(number.getLabel() != "")?number.getLabel().c_str():number.getName().c_str() encoding:[NSString defaultCStringEncoding]], number.getValue()]];
+    }
+    return self;
+}
+-(void)sliderValueChanged:(UISlider *)sender
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return;
+    number[0].setValue(sender.value);
+    onelab::server::instance()->set(number[0]);
+    [label setText:[NSString stringWithFormat:@"%s %f" ,(number[0].getLabel() != "")?number[0].getLabel().c_str():number[0].getName().c_str(), number[0].getValue()]];
+    if(onelab_cb("check") == 1)
+        [[NSNotificationCenter defaultCenter] postNotificationName:@"requestRender" object:nil];
+}
+-(void)setFrame:(CGRect)frame
+{
+    [slider setFrame:frame];
+}
+-(UISlider *)getSlider
+{
+    return slider;
+}
+-(bool)isReadOnly
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return YES;
+    return number[0].getReadOnly();
+}
++(double)getHeight
+{
+    return 60.0f;
+}
+@end
+
+@implementation parameterNumberTextbox
+-(id)initWithNumber:(onelab::number)number
+{
+    self = [super init];
+    if(self)
+    {
+        label.alpha = (number.getReadOnly())? 0.439216f : 1.0f;
+        [label setText:[NSString stringWithCString:(number.getLabel() != "")?number.getLabel().c_str():number.getName().c_str() encoding:[NSString defaultCStringEncoding]]];
+        name = [NSString stringWithCString:number.getName().c_str() encoding:[NSString defaultCStringEncoding]];
+        textbox = [[UITextField alloc] init];
+        [textbox setBorderStyle:UITextBorderStyleRoundedRect];
+        [textbox setKeyboardType:UIKeyboardTypeNumberPad];
+        [textbox setText:[NSString stringWithFormat:@"%f", number.getValue()]];
+        [textbox setDelegate:self];
+    }
+    return self;
+}
+-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return YES;
+    number[0].setValue([textField.text doubleValue]);
+    onelab::server::instance()->set(number[0]);
+    return YES;
+}
+-(BOOL)textFieldShouldReturn:(UITextField *)textField
+{
+    return [textField endEditing:YES];
+}
+-(void)setFrame:(CGRect)frame
+{
+    [textbox setFrame:frame];
+}
+-(UITextField *)getTextbox
+{
+    return textbox;
+}
+-(bool)isReadOnly
+{
+    std::vector<onelab::number> number;
+    onelab::server::instance()->get(number,[name UTF8String]);
+    if(number.size() < 1) return YES;
+    return number[0].getReadOnly();
+}
++(double)getHeight
+{
+    return 60.f;
+}
+@end
-- 
GitLab