1#import "SkOptionsTableViewController.h"
2#include "SkEvent.h"
3#include "SkTArray.h"
4
5@implementation SkOptionItem
6@synthesize fCell, fItem;
7- (void)dealloc {
8    [fCell release];
9    [super dealloc];
10}
11@end
12
13@implementation SkOptionListItem
14@synthesize fOptions;
15- (void)dealloc {
16    [fOptions release];
17    [super dealloc];
18}
19@end
20
21@implementation SkOptionsTableViewController
22
23@synthesize fItems, fCurrentList;
24
25- (id)initWithStyle:(UITableViewStyle)style {
26    self = [super initWithStyle:style];
27    if (self) {
28        self.fItems = [NSMutableArray array];
29    }
30    return self;
31}
32
33//SkUIViewOptionsDelegate
34- (void) view:(SkUIView*)view didAddMenu:(const SkOSMenu*)menu {}
35- (void) view:(SkUIView*)view didUpdateMenu:(SkOSMenu*)menu {
36    [self updateMenu:menu];
37}
38
39- (NSUInteger)convertPathToIndex:(NSIndexPath*)path {
40    NSUInteger index = 0;
41    for (NSInteger i = 0; i < path.section; ++i) {
42        index += (*fMenus)[i]->getCount();
43    }
44    return index + path.row;
45}
46
47- (void)registerMenus:(const SkTDArray<SkOSMenu*>*)menus {
48    fMenus = menus;
49    for (NSUInteger i = 0; i < fMenus->count(); ++i) {
50        [self loadMenu:(*fMenus)[i]];
51    }
52}
53
54- (void)updateMenu:(SkOSMenu*)menu {
55    // the first menu is always assumed to be the static, the second is
56    // repopulated every time over and over again
57    int menuIndex = fMenus->find(menu);
58    if (menuIndex >= 0 && menuIndex < fMenus->count()) {
59        NSUInteger first = 0;
60        for (NSInteger i = 0; i < menuIndex; ++i) {
61            first += (*fMenus)[i]->getCount();
62        }
63        [fItems removeObjectsInRange:NSMakeRange(first, [fItems count] - first)];
64        [self loadMenu:menu];
65    }
66    [self.tableView reloadData];
67}
68
69- (void)loadMenu:(SkOSMenu*)menu {
70    const SkOSMenu::Item* menuitems[menu->getCount()];
71    menu->getItems(menuitems);
72    for (int i = 0; i < menu->getCount(); ++i) {
73        const SkOSMenu::Item* item = menuitems[i];
74        NSString* title = [NSString stringWithUTF8String:item->getLabel()];
75
76        if (SkOSMenu::kList_Type == item->getType()) {
77            int value = 0;
78            SkOptionListItem* List = [[SkOptionListItem alloc] init];
79
80            List.fItem = item;
81            List.fOptions = [[SkOptionListController alloc] initWithStyle:UITableViewStyleGrouped];
82
83            int count = 0;
84            SkOSMenu::FindListItemCount(*item->getEvent(), &count);
85            SkTArray<SkString> options;
86            options.resize_back(count);
87            SkOSMenu::FindListItems(*item->getEvent(), &options.front());
88            for (int i = 0; i < count; ++i)
89                [List.fOptions addOption:[NSString stringWithUTF8String:options[i].c_str()]];
90            SkOSMenu::FindListIndex(*item->getEvent(), item->getSlotName(), &value);
91
92            List.fOptions.fSelectedIndex = value;
93            List.fCell = [self createList:title
94                                      default:[List.fOptions getSelectedOption]];
95            List.fOptions.fParentCell = List.fCell;
96            [fItems addObject:List];
97            [List release];
98        }
99        else {
100            SkOptionItem* option = [[SkOptionItem alloc] init];
101            option.fItem = item;
102
103            bool state = false;
104            SkString str;
105            SkOSMenu::TriState tristate;
106            switch (item->getType()) {
107                case SkOSMenu::kAction_Type:
108                    option.fCell = [self createAction:title];
109                    break;
110                case SkOSMenu::kSwitch_Type:
111                    SkOSMenu::FindSwitchState(*item->getEvent(), item->getSlotName(), &state);
112                    option.fCell = [self createSwitch:title default:(BOOL)state];
113                    break;
114                case SkOSMenu::kSlider_Type:
115                    SkScalar min, max, value;
116                    SkOSMenu::FindSliderValue(*item->getEvent(), item->getSlotName(), &value);
117                    SkOSMenu::FindSliderMin(*item->getEvent(), &min);
118                    SkOSMenu::FindSliderMax(*item->getEvent(), &max);
119                    option.fCell = [self createSlider:title
120                                                  min:min
121                                                  max:max
122                                              default:value];
123                    break;
124                case SkOSMenu::kTriState_Type:
125                    SkOSMenu::FindTriState(*item->getEvent(), item->getSlotName(), &tristate);
126                    option.fCell = [self createTriState:title default:(int)tristate];
127                    break;
128                case SkOSMenu::kTextField_Type:
129                    SkOSMenu::FindText(*item->getEvent(), item->getSlotName(), &str);
130                    option.fCell = [self createTextField:title
131                                                 default:[NSString stringWithUTF8String:str.c_str()]];
132                    break;
133                default:
134                    break;
135            }
136            [fItems addObject:option];
137            [option release];
138        }
139    }
140}
141
142- (void)valueChanged:(id)sender {
143    UITableViewCell* cell = (UITableViewCell*)(((UIView*)sender).superview);
144    NSUInteger index = [self convertPathToIndex:[self.tableView indexPathForCell:cell]];
145    SkOptionItem* item = (SkOptionItem*)[fItems objectAtIndex:index];
146    if ([sender isKindOfClass:[UISlider class]]) {//Slider
147        UISlider* slider = (UISlider *)sender;
148        cell.detailTextLabel.text = [NSString stringWithFormat:@"%1.1f", slider.value];
149        item.fItem->setScalar(slider.value);
150    }
151    else if ([sender isKindOfClass:[UISwitch class]]) {//Switch
152        UISwitch* switch_ = (UISwitch *)sender;
153        item.fItem->setBool(switch_.on);
154    }
155    else if ([sender isKindOfClass:[UITextField class]]) { //TextField
156        UITextField* textField = (UITextField *)sender;
157        [textField resignFirstResponder];
158        item.fItem->setString([textField.text UTF8String]);
159    }
160    else if ([sender isKindOfClass:[UISegmentedControl class]]) { //Action
161        UISegmentedControl* segmented = (UISegmentedControl *)sender;
162        SkOSMenu::TriState state;
163        if (2 == segmented.selectedSegmentIndex) {
164            state = SkOSMenu::kMixedState;
165        } else {
166            state = (SkOSMenu::TriState)segmented.selectedSegmentIndex;
167        }
168        item.fItem->setTriState(state);
169    }
170    else{
171        NSLog(@"unknown");
172    }
173    item.fItem->postEvent();
174}
175
176- (UITableViewCell*)createAction:(NSString*)title {
177    UITableViewCell* cell = [[[UITableViewCell alloc]
178                              initWithStyle:UITableViewCellStyleValue1
179                              reuseIdentifier:nil] autorelease];
180    cell.textLabel.text = title;
181    return cell;
182}
183
184- (UITableViewCell*)createSwitch:(NSString*)title default:(BOOL)state {
185    UITableViewCell* cell = [[[UITableViewCell alloc]
186                              initWithStyle:UITableViewCellStyleValue1
187                              reuseIdentifier:nil] autorelease];
188    cell.textLabel.text = title;
189    cell.selectionStyle = UITableViewCellSelectionStyleNone;
190    UISwitch* switchView = [[UISwitch alloc] initWithFrame:CGRectZero];
191    [switchView setOn:state animated:NO];
192    [switchView addTarget:self
193                   action:@selector(valueChanged:)
194         forControlEvents:UIControlEventValueChanged];
195    cell.accessoryView = switchView;
196    [switchView release];
197    return cell;
198}
199
200- (UITableViewCell*)createSlider:(NSString*)title
201                             min:(float)min
202                             max:(float)max
203                         default:(float)value {
204    UITableViewCell* cell = [[[UITableViewCell alloc]
205                             initWithStyle:UITableViewCellStyleValue1
206                             reuseIdentifier:nil] autorelease];
207    cell.textLabel.text = title;
208    cell.selectionStyle = UITableViewCellSelectionStyleNone;
209    UISlider* sliderView = [[UISlider alloc] init];
210    sliderView.value = value;
211    sliderView.minimumValue = min;
212    sliderView.maximumValue = max;
213    [sliderView addTarget:self
214                   action:@selector(valueChanged:)
215         forControlEvents:UIControlEventValueChanged];
216    cell.detailTextLabel.text = [NSString stringWithFormat:@"%1.1f", value];
217    cell.accessoryView = sliderView;
218    [sliderView release];
219    return cell;
220}
221
222- (UITableViewCell*)createTriState:(NSString*)title default:(int)index {
223    UITableViewCell* cell = [[[UITableViewCell alloc]
224                              initWithStyle:UITableViewCellStyleValue1
225                              reuseIdentifier:nil] autorelease];
226    cell.textLabel.text = title;
227    cell.selectionStyle = UITableViewCellSelectionStyleNone;
228    NSArray* items = [NSArray arrayWithObjects:@"Off", @"On", @"Mixed", nil];
229    UISegmentedControl* segmented = [[UISegmentedControl alloc] initWithItems:items];
230    segmented.selectedSegmentIndex = (index == -1) ? 2 : index;
231    segmented.segmentedControlStyle = UISegmentedControlStyleBar;
232    [segmented addTarget:self
233                  action:@selector(valueChanged:)
234        forControlEvents:UIControlEventValueChanged];
235    cell.accessoryView = segmented;
236    [segmented release];
237    return cell;
238}
239
240- (UITableViewCell*)createTextField:(NSString*)title
241                            default:(NSString*)value {
242    UITableViewCell* cell = [[[UITableViewCell alloc]
243                              initWithStyle:UITableViewCellStyleValue1
244                              reuseIdentifier:nil] autorelease];
245    cell.textLabel.text = title;
246    cell.selectionStyle = UITableViewCellSelectionStyleNone;
247    UITextField* textField = [[UITextField alloc]
248                              initWithFrame:CGRectMake(0, 10, 150, 25)];
249    textField.adjustsFontSizeToFitWidth = YES;
250    textField.textAlignment = NSTextAlignmentRight;
251    textField.textColor = cell.detailTextLabel.textColor;
252    textField.placeholder = value;
253    textField.returnKeyType = UIReturnKeyDone;
254    [textField addTarget:self
255                  action:@selector(valueChanged:)
256        forControlEvents:UIControlEventEditingDidEndOnExit];
257    cell.accessoryView = textField;
258    [textField release];
259    return cell;
260}
261
262- (UITableViewCell*)createList:(NSString*)title default:(NSString*)value{
263    UITableViewCell* cell = [[[UITableViewCell alloc]
264                              initWithStyle:UITableViewCellStyleValue1
265                              reuseIdentifier:nil] autorelease];
266    cell.textLabel.text = title;
267    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
268    cell.detailTextLabel.text = value;
269    return cell;
270}
271
272#pragma mark -
273#pragma mark Table view data source
274
275- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
276    return fMenus->count();
277}
278
279- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
280    return [NSString stringWithUTF8String:(*fMenus)[section]->getTitle()];
281}
282
283- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
284    return (*fMenus)[section]->getCount();
285}
286
287- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
288    return ((SkOptionItem*)[fItems objectAtIndex:[self convertPathToIndex:indexPath]]).fCell;
289}
290
291#pragma mark -
292#pragma mark Table view delegate
293
294- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
295    UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
296    id item = [fItems objectAtIndex:[self convertPathToIndex:indexPath]];
297
298    if ([item isKindOfClass:[SkOptionListItem class]]) {
299        SkOptionListItem* list = (SkOptionListItem*)item;
300        self.fCurrentList = list;
301        self.navigationController.delegate = self;
302        [self.navigationController pushViewController:list.fOptions animated:YES];
303    }
304    else if ([item isKindOfClass:[SkOptionItem class]]) {
305        if (UITableViewCellSelectionStyleNone != cell.selectionStyle) { //Actions
306            SkOptionItem* action = (SkOptionItem*)item;
307            action.fItem->postEvent();
308        }
309    }
310    else{
311        NSLog(@"unknown");
312    }
313
314    [self.tableView deselectRowAtIndexPath:indexPath animated:YES];
315}
316
317#pragma mark -
318#pragma mark Navigation controller delegate
319
320- (void)navigationController:(UINavigationController *)navigationController
321      willShowViewController:(UIViewController *)viewController
322                    animated:(BOOL)animated {
323    if (self == viewController) { //when a List option is popped, trigger event
324        NSString* selectedOption = [fCurrentList.fOptions getSelectedOption];
325        fCurrentList.fCell.detailTextLabel.text = selectedOption;
326        fCurrentList.fItem->setInt(fCurrentList.fOptions.fSelectedIndex);
327        fCurrentList.fItem->postEvent();
328    }
329}
330
331#pragma mark -
332#pragma mark Memory management
333
334- (void)dealloc {
335    self.fItems = nil;
336    [super dealloc];
337}
338
339@end