1 /* xscreensaver, Copyright (c) 2012 Jamie Zawinski <jwz@jwz.org>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
11 * This implements the top-level screen-saver selection list in the iOS app.
14 #ifdef USE_IPHONE // whole file
17 #import "SaverListController.h"
20 #define countof(x) (sizeof((x))/sizeof((*x)))
23 @implementation SaverListController
25 - (id)initWithNames:(NSArray *)names descriptions:(NSDictionary *)descs;
29 [self reload:names descriptions:descs];
34 - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tv
36 int n = countof(list_by_letter);
37 NSMutableArray *a = [NSMutableArray arrayWithCapacity: n];
38 for (int i = 0; i < n; i++) {
40 s[0] = (i == 'Z'-'A'+1 ? '#' : i+'A');
42 [a addObject: [NSString stringWithCString:s
43 encoding:NSASCIIStringEncoding]];
49 - (void) reload:(NSArray *)names descriptions:(NSDictionary *)descs
52 [descriptions release];
53 descriptions = [descs retain];
55 int n = countof(list_by_letter);
56 for (int i = 0; i < n; i++) {
57 list_by_letter[i] = [[NSMutableArray alloc] init];
60 for (NSString *name in names) {
61 int index = ([name cStringUsingEncoding: NSASCIIStringEncoding])[0];
62 if (index >= 'a' && index <= 'z')
64 if (index >= 'A' && index <= 'Z')
68 [list_by_letter[index] addObject: name];
71 active_section_count = 0;
72 letter_sections = [[[NSMutableArray alloc] init] retain];
73 section_titles = [[[NSMutableArray alloc] init] retain];
74 for (int i = 0; i < n; i++) {
75 if ([list_by_letter[i] count] > 0) {
76 active_section_count++;
77 [letter_sections addObject: list_by_letter[i]];
79 [section_titles addObject: [NSString stringWithFormat: @"%c", i+'A']];
81 [section_titles addObject: @"#"];
84 [self.tableView reloadData];
88 - (NSString *)tableView:(UITableView *)tv
89 titleForHeaderInSection:(NSInteger)section
91 return [section_titles objectAtIndex: section];
94 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tv
96 return active_section_count;
100 - (NSInteger)tableView:(UITableView *)tv
101 numberOfRowsInSection:(NSInteger)section
103 return [[letter_sections objectAtIndex: section] count];
106 - (NSInteger)tableView:(UITableView *)tv
107 sectionForSectionIndexTitle:(NSString *)title
108 atIndex:(NSInteger) index
111 for (NSString *sectionTitle in section_titles) {
112 if ([sectionTitle isEqualToString: title])
120 - (UITableViewCell *)tableView:(UITableView *)tv
121 cellForRowAtIndexPath:(NSIndexPath *)ip
124 [[letter_sections objectAtIndex: [ip indexAtPosition: 0]]
125 objectAtIndex: [ip indexAtPosition: 1]];
126 NSString *desc = [descriptions objectForKey:id];
128 UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier: id];
130 cell = [[[UITableViewCell alloc]
132 ? UITableViewCellStyleSubtitle
133 : UITableViewCellStyleDefault)
136 cell.textLabel.text = id;
138 cell.detailTextLabel.text = desc;
144 - (void)tapTimer:(NSTimer *)t
153 - (void)tableView:(UITableView *)tv
154 didSelectRowAtIndexPath:(NSIndexPath *)ip
156 UITableViewCell *cell = [tv cellForRowAtIndexPath: ip];
157 selected = cell.textLabel.text;
158 [self.navigationItem.leftBarButtonItem setEnabled: !!selected];
159 [self.navigationItem.rightBarButtonItem setEnabled: !!selected];
161 if (tap_count == 0) { // First tap
163 last_tap = [[ip copy] retain];
164 tap_timer = [NSTimer scheduledTimerWithTimeInterval: 0.3
166 selector:@selector(tapTimer:)
170 } else if (tap_count == 1 && tap_timer && // Second tap
171 [ip isEqual:last_tap]) {
172 [tap_timer invalidate];
178 // Press the leftmost button in the button-bar.
179 UIBarButtonItem *b = self.navigationItem.leftBarButtonItem;
180 [[b target] performSelector: [b action] withObject: cell];
182 } else if (! [ip isEqual:last_tap]) { // Tap on a new row
183 if (tap_timer) [tap_timer invalidate];
190 /* We can't select a row immediately after creation, but selecting it
191 a little while later works (presumably after redisplay has happened)
194 - (void) scrollToCB: (NSTimer *) timer
196 NSString *name = [timer userInfo];
201 for (NSArray *a in letter_sections) {
203 for (NSString *n in a) {
204 ok = [n isEqualToString: name];
212 NSIndexPath *ip = [NSIndexPath indexPathForRow: j inSection: i];
213 [self.tableView selectRowAtIndexPath:ip
215 scrollPosition: UITableViewScrollPositionMiddle];
216 [self tableView:self.tableView didSelectRowAtIndexPath:ip];
221 - (void) scrollTo: (NSString *) name
223 [NSTimer scheduledTimerWithTimeInterval: 0
225 selector:@selector(scrollToCB:)
231 - (void)viewWillAppear:(BOOL)animated
233 /* Hitting the back button and returing to this view deselects,
234 and we can't re-select it from here, so again, do it once
235 we return to the event loop.
238 [NSTimer scheduledTimerWithTimeInterval: 0
240 selector:@selector(scrollToCB:)
243 [super viewWillAppear:animated];
247 - (NSString *) selected
253 - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)o
261 for (int i = 0; i < countof(list_by_letter); i++)
262 [list_by_letter[i] release];
263 [letter_sections release];
264 [section_titles release];
265 [descriptions release];
272 #endif // USE_IPHONE -- whole file