![]() |
API 0.9.5
|
00001 /* 00002 * CPUserDefaultsController.j 00003 * AppKit 00004 * 00005 * Portions based on NSUserDefaultsController.m (2009-06-04) in Cocotron (http://www.cocotron.org/) 00006 * Copyright (c) 2006-2007 Christopher J. W. Lloyd 00007 * 00008 * Created by Alexander Ljungberg. 00009 * Copyright 2011, WireLoad Inc. 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Lesser General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2.1 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Lesser General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Lesser General Public 00022 * License along with this library; if not, write to the Free Software 00023 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00024 */ 00025 00026 00027 00028 var SharedUserDefaultsController = nil; 00029 00030 @implementation CPUserDefaultsController : CPController 00031 { 00032 CPUserDefaults _defaults; 00033 CPDictionary _initialValues; 00034 BOOL _appliesImmediately; 00035 } 00036 00037 + (id)sharedUserDefaultsController 00038 { 00039 if (!SharedUserDefaultsController) 00040 SharedUserDefaultsController = [[CPUserDefaultsController alloc] initWithDefaults:nil initialValues:nil]; 00041 00042 return SharedUserDefaultsController; 00043 } 00044 00045 - (id)initWithDefaults:(CPUserDefaults)someDefaults initialValues:(CPDictionary)initialValues 00046 { 00047 if (self = [super init]) 00048 { 00049 if (!someDefaults) 00050 someDefaults = [CPUserDefaults standardUserDefaults]; 00051 00052 _defaults = someDefaults; 00053 _initialValues = [initialValues copy]; 00054 _appliesImmediately = YES; 00055 _valueProxy = [[_CPUserDefaultsControllerProxy alloc] initWithController:self]; 00056 } 00057 00058 return self; 00059 } 00060 00061 - (id)values 00062 { 00063 return _valueProxy; 00064 } 00065 00066 - (BOOL)hasUnappliedChanges 00067 { 00068 return [_valueProxy hasUnappliedChanges]; 00069 } 00070 00071 - (void)save:(id)sender 00072 { 00073 [_valueProxy save]; 00074 } 00075 00076 - (void)revert:(id)sender 00077 { 00078 [_valueProxy revert]; 00079 } 00080 00081 - (void)revertToInitialValues:(id)sender 00082 { 00083 [_valueProxy revertToInitialValues]; 00084 } 00085 00086 @end 00087 00088 00089 var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey"; 00090 00091 @implementation CPUserDefaultsController (CPCoding) 00092 00093 - (id)initWithCoder:(CPCoder)aCoder 00094 { 00095 if ([aCoder decodeBoolForKey:CPUserDefaultsControllerSharedKey]) 00096 return [CPUserDefaultsController sharedUserDefaultsController]; 00097 00098 self = [super initWithCoder:aCoder]; 00099 00100 if (self) 00101 { 00102 [CPException raise:CPUnsupportedMethodException reason:@"decoding of non-shared CPUserDefaultsController not implemented"]; 00103 } 00104 00105 return self; 00106 } 00107 00108 - (void)encodeWithCoder:(CPCoder)aCoder 00109 { 00110 [super encodeWithCoder:aCoder]; 00111 00112 if (self === SharedUserDefaultsController) 00113 { 00114 [aCoder encodeBool:YES forKey:CPUserDefaultsControllerSharedKey]; 00115 return; 00116 } 00117 00118 [CPException raise:CPUnsupportedMethodException reason:@"encoding of non-shared CPUserDefaultsController not implemented"]; 00119 } 00120 00121 @end 00122 00123 00124 @implementation _CPUserDefaultsControllerProxy : CPObject 00125 { 00126 CPUserDefaultsController _controller; 00127 // TODO Could be optimised with a JS dict. 00128 CPMutableDictionary _cachedValues; 00129 } 00130 00131 - (id)initWithController:(CPUserDefaultsController)aController 00132 { 00133 if (self = [super init]) 00134 { 00135 _controller = aController; 00136 _cachedValues = [CPMutableDictionary dictionary]; 00137 00138 [[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:CPUserDefaultsDidChangeNotification object:[_controller defaults]]; 00139 } 00140 00141 return self; 00142 } 00143 00144 - (void)dealloc 00145 { 00146 // FIXME No dealloc in Cappuccino. 00147 [[CPNotificationCenter defaultCenter] removeObserver:self]; 00148 [super dealloc]; 00149 } 00150 00151 - (id)valueForKey:(CPString)aKey 00152 { 00153 var value = [_cachedValues objectForKey:aKey]; 00154 if (value === nil) 00155 { 00156 value = [[_controller defaults] objectForKey:aKey]; 00157 if (value === nil) 00158 value = [[_controller initialValues] objectForKey:aKey]; 00159 00160 if (value !== nil) 00161 [_cachedValues setObject:value forKey:aKey]; 00162 } 00163 return value; 00164 } 00165 00166 - (void)setValue:(id)aValue forKey:(CPString)aKey 00167 { 00168 [self willChangeValueForKey:aKey]; 00169 [_cachedValues setObject:aValue forKey:aKey]; 00170 if ([_controller appliesImmediately]) 00171 [[_controller defaults] setObject:aValue forKey:aKey]; 00172 [self didChangeValueForKey:aKey]; 00173 } 00174 00175 00176 - (void)revert 00177 { 00178 var keys = [_cachedValues allKeys], 00179 keysCount = [keys count]; 00180 00181 while(keysCount--) 00182 { 00183 var key = keys[keysCount]; 00184 [self willChangeValueForKey:key]; 00185 [_cachedValues removeObjectForKey:key]; 00186 [self didChangeValueForKey:key]; 00187 } 00188 } 00189 00190 - (void)save 00191 { 00192 var keys = [_cachedValues allKeys], 00193 keysCount = [keys count]; 00194 00195 while(keysCount--) 00196 { 00197 var key = keys[keysCount]; 00198 [[_controller defaults] setObject:[_cachedValues objectForKey:key] forKey:key]; 00199 } 00200 } 00201 00202 - (void)revertToInitialValues 00203 { 00204 var initial = [_controller initialValues], 00205 keys = [_cachedValues allKeys], 00206 keysCount = [keys count]; 00207 00208 while(keysCount--) 00209 { 00210 var key = keys[keysCount]; 00211 [self willChangeValueForKey:key]; 00212 00213 var initialValue = [initial objectForKey:key]; 00214 if (initialValue !== nil) 00215 [_cachedValues setObject:initialValue forKey:key]; 00216 else 00217 [_cachedValues removeObjectForKey:key]; 00218 00219 [self didChangeValueForKey:key]; 00220 00221 } 00222 } 00223 00224 - (void)userDefaultsDidChange:(CPNotification)aNotification 00225 { 00226 var defaults = [_controller defaults], 00227 keys = [_cachedValues allKeys], 00228 keysCount = [keys count]; 00229 00230 while(keysCount--) 00231 { 00232 var key = keys[keysCount], 00233 value = [_cachedValues objectForKey:key], 00234 newValue = [defaults objectForKey:key]; 00235 00236 if (![value isEqual:newValue]) 00237 { 00238 [self willChangeValueForKey:key]; 00239 [_cachedValues setObject:newValue forKey:key]; 00240 [self didChangeValueForKey:key]; 00241 } 00242 } 00243 } 00244 00245 - (BOOL)hasUnappliedChanges 00246 { 00247 var defaults = [_controller defaults], 00248 keys = [_cachedValues allKeys], 00249 keysCount = [keys count]; 00250 00251 while(keysCount--) 00252 { 00253 var key = keys[keysCount], 00254 value = [_cachedValues objectForKey:key], 00255 newValue = [defaults objectForKey:key]; 00256 00257 if (![value isEqual:newValue]) 00258 return YES; 00259 } 00260 00261 return NO; 00262 } 00263 00264 @end 00265 00266 00267 @implementation CPUserDefaultsController (CPSynthesizedAccessors) 00268 00272 - (CPUserDefaults)defaults 00273 { 00274 return _defaults; 00275 } 00276 00280 - (CPDictionary)initialValues 00281 { 00282 return _initialValues; 00283 } 00284 00288 - (void)setInitialValues:(CPDictionary)aValue 00289 { 00290 _initialValues = aValue; 00291 } 00292 00296 - (BOOL)appliesImmediately 00297 { 00298 return _appliesImmediately; 00299 } 00300 00304 - (void)setAppliesImmediately:(BOOL)aValue 00305 { 00306 _appliesImmediately = aValue; 00307 } 00308 00309 @end