]>
Commit | Line | Data |
---|---|---|
1 | /* WinterBoard - Theme Manager for the iPhone | |
2 | * Copyright (C) 2008 Jay Freeman (saurik) | |
3 | */ | |
4 | ||
5 | /* | |
6 | * Redistribution and use in source and binary | |
7 | * forms, with or without modification, are permitted | |
8 | * provided that the following conditions are met: | |
9 | * | |
10 | * 1. Redistributions of source code must retain the | |
11 | * above copyright notice, this list of conditions | |
12 | * and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the | |
14 | * above copyright notice, this list of conditions | |
15 | * and the following disclaimer in the documentation | |
16 | * and/or other materials provided with the | |
17 | * distribution. | |
18 | * 3. The name of the author may not be used to endorse | |
19 | * or promote products derived from this software | |
20 | * without specific prior written permission. | |
21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' | |
23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, | |
24 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
25 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
26 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE | |
27 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
28 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
29 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
30 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
31 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |
32 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
33 | * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN | |
34 | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF | |
35 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
36 | */ | |
37 | ||
38 | #import <Foundation/Foundation.h> | |
39 | #import <CoreGraphics/CGGeometry.h> | |
40 | #import <UIKit/UIKit.h> | |
41 | ||
42 | #define _trace() NSLog(@"WE:_trace(%u)", __LINE__); | |
43 | ||
44 | static NSString *plist_; | |
45 | static NSMutableDictionary *settings_; | |
46 | ||
47 | @interface WBThemeTableViewCell : UITableViewCell { | |
48 | UILabel *label; | |
49 | } | |
50 | ||
51 | @end | |
52 | ||
53 | @implementation WBThemeTableViewCell | |
54 | ||
55 | ||
56 | @end | |
57 | ||
58 | @interface WBApplication : UIApplication < | |
59 | UITableViewDataSource, | |
60 | UITableViewDelegate | |
61 | > { | |
62 | UIWindow *window_; | |
63 | UITableView *themesTable_; | |
64 | NSMutableArray *themesArray_; | |
65 | } | |
66 | ||
67 | @end | |
68 | ||
69 | @implementation WBApplication | |
70 | ||
71 | - (void) dealloc { | |
72 | [window_ release]; | |
73 | [themesTable_ release]; | |
74 | [themesArray_ release]; | |
75 | [super dealloc]; | |
76 | } | |
77 | ||
78 | - (void) applicationWillTerminate:(UIApplication *)application { | |
79 | [settings_ writeToFile:plist_ atomically:YES]; | |
80 | system("killall SpringBoard"); | |
81 | } | |
82 | ||
83 | - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { | |
84 | UITableViewCell *cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero] autorelease]; | |
85 | NSMutableDictionary *theme = [themesArray_ objectAtIndex:[indexPath row]]; | |
86 | cell.text = [theme objectForKey:@"Name"]; | |
87 | cell.hidesAccessoryWhenEditing = NO; | |
88 | NSNumber *active = [theme objectForKey:@"Active"]; | |
89 | BOOL inactive = active == nil || ![active boolValue]; | |
90 | cell.accessoryType = inactive ? UITableViewCellAccessoryNone : UITableViewCellAccessoryCheckmark; | |
91 | return cell; | |
92 | } | |
93 | ||
94 | - (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { | |
95 | UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; | |
96 | NSMutableDictionary *theme = [themesArray_ objectAtIndex:[indexPath row]]; | |
97 | NSNumber *active = [theme objectForKey:@"Active"]; | |
98 | BOOL inactive = active == nil || ![active boolValue]; | |
99 | [theme setObject:[NSNumber numberWithBool:inactive] forKey:@"Active"]; | |
100 | cell.accessoryType = inactive ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone; | |
101 | [themesTable_ deselectRowAtIndexPath:(NSIndexPath *)indexPath animated:YES]; | |
102 | } | |
103 | ||
104 | - (NSInteger) tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section { | |
105 | return [themesArray_ count]; | |
106 | } | |
107 | ||
108 | - (UITableViewCellEditingStyle) tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { | |
109 | return UITableViewCellEditingStyleNone; | |
110 | } | |
111 | ||
112 | - (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { | |
113 | NSUInteger fromIndex = [fromIndexPath row]; | |
114 | NSUInteger toIndex = [toIndexPath row]; | |
115 | if (fromIndex == toIndex) | |
116 | return; | |
117 | NSMutableDictionary *theme = [[[themesArray_ objectAtIndex:fromIndex] retain] autorelease]; | |
118 | [themesArray_ removeObjectAtIndex:fromIndex]; | |
119 | [themesArray_ insertObject:theme atIndex:toIndex]; | |
120 | } | |
121 | ||
122 | - (BOOL) tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { | |
123 | return YES; | |
124 | } | |
125 | ||
126 | - (void) applicationDidFinishLaunching:(id)unused { | |
127 | window_ = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].applicationFrame]; | |
128 | [window_ makeKeyAndVisible]; | |
129 | ||
130 | plist_ = [[NSString stringWithFormat:@"%@/Library/Preferences/com.saurik.WinterBoard.plist", | |
131 | NSHomeDirectory() | |
132 | ] retain]; | |
133 | ||
134 | settings_ = [[NSMutableDictionary alloc] initWithContentsOfFile:plist_]; | |
135 | ||
136 | themesArray_ = [settings_ objectForKey:@"Themes"]; | |
137 | if (themesArray_ == nil) { | |
138 | if (NSString *theme = [settings_ objectForKey:@"Theme"]) { | |
139 | themesArray_ = [[NSArray arrayWithObject:[[NSDictionary dictionaryWithObjectsAndKeys: | |
140 | theme, @"Name", | |
141 | [NSNumber numberWithBool:YES], @"Active", | |
142 | nil] mutableCopy]] mutableCopy]; | |
143 | ||
144 | [settings_ removeObjectForKey:@"Theme"]; | |
145 | } | |
146 | ||
147 | if (themesArray_ == nil) | |
148 | themesArray_ = [NSMutableArray arrayWithCapacity:16]; | |
149 | [settings_ setObject:themesArray_ forKey:@"Themes"]; | |
150 | } | |
151 | ||
152 | themesArray_ = [themesArray_ retain]; | |
153 | ||
154 | NSMutableSet *themesSet = [NSMutableSet setWithCapacity:32]; | |
155 | for (NSMutableDictionary *theme in themesArray_) | |
156 | if (NSString *name = [theme objectForKey:@"Name"]) | |
157 | [themesSet addObject:name]; | |
158 | ||
159 | NSFileManager *manager = [NSFileManager defaultManager]; | |
160 | ||
161 | NSMutableArray *themes = [NSMutableArray arrayWithCapacity:32]; | |
162 | [themes addObjectsFromArray:[manager contentsOfDirectoryAtPath:@"/Library/Themes" error:NULL]]; | |
163 | [themes addObjectsFromArray:[manager contentsOfDirectoryAtPath:[NSString stringWithFormat:@"%@/Library/SummerBoard/Themes", NSHomeDirectory()] error:NULL]]; | |
164 | ||
165 | for (NSString *theme in themes) { | |
166 | if ([theme hasSuffix:@".theme"]) | |
167 | theme = [theme substringWithRange:NSMakeRange(0, [theme length] - 6)]; | |
168 | if ([themesSet containsObject:theme]) | |
169 | continue; | |
170 | [themesSet addObject:theme]; | |
171 | [themesArray_ addObject:[[NSDictionary dictionaryWithObjectsAndKeys: | |
172 | theme, @"Name", | |
173 | [NSNumber numberWithBool:NO], @"Active", | |
174 | nil] mutableCopy]]; | |
175 | } | |
176 | ||
177 | themesTable_ = [[UITableView alloc] initWithFrame:window_.bounds]; | |
178 | [window_ addSubview:themesTable_]; | |
179 | ||
180 | [themesTable_ setDataSource:self]; | |
181 | [themesTable_ setDelegate:self]; | |
182 | ||
183 | [themesTable_ setEditing:YES animated:NO]; | |
184 | themesTable_.allowsSelectionDuringEditing = YES; | |
185 | ||
186 | [themesTable_ setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine]; | |
187 | } | |
188 | ||
189 | @end | |
190 | ||
191 | int main(int argc, char *argv[]) { | |
192 | NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
193 | ||
194 | int value = UIApplicationMain(argc, argv, @"WBApplication", @"WBApplication"); | |
195 | ||
196 | [pool release]; | |
197 | return value; | |
198 | } |