mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
CPUserDefaultsController.
This commit is contained in:
@@ -93,6 +93,7 @@
|
||||
@import "CPToolbarItem.j"
|
||||
@import "_CPToolTip.j"
|
||||
@import "CPTreeNode.j"
|
||||
@import "CPUserDefaultsController.j"
|
||||
@import "CPView.j"
|
||||
@import "CPViewAnimation.j"
|
||||
@import "CPViewController.j"
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* CPUserDefaultsController.j
|
||||
* AppKit
|
||||
*
|
||||
* Portions based on NSUserDefaultsController.m (2009-06-04) in Cocotron (http://www.cocotron.org/)
|
||||
* Copyright (c) 2006-2007 Christopher J. W. Lloyd
|
||||
*
|
||||
* Created by Alexander Ljungberg.
|
||||
* Copyright 2011, WireLoad Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
@import <Foundation/CPString.j>
|
||||
@import <AppKit/CPController.j>
|
||||
|
||||
var SharedUserDefaultsController = nil;
|
||||
|
||||
@implementation CPUserDefaultsController : CPController
|
||||
{
|
||||
CPUserDefaults _defaults @accessors(readonly, property=defaults);
|
||||
CPDictionary _initialValues @accessors(property=initialValues);
|
||||
BOOL _appliesImmediately @accessors(property=appliesImmediately);
|
||||
}
|
||||
|
||||
+ (id)sharedUserDefaultsController
|
||||
{
|
||||
if (!SharedUserDefaultsController)
|
||||
SharedUserDefaultsController = [[CPUserDefaultsController alloc] initWithDefaults:nil initialValues:nil];
|
||||
|
||||
return SharedUserDefaultsController;
|
||||
}
|
||||
|
||||
- (id)initWithDefaults:(CPUserDefaults)someDefaults initialValues:(CPDictionary)initialValues
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
if (!someDefaults)
|
||||
someDefaults = [CPUserDefaults standardUserDefaults];
|
||||
|
||||
_defaults = someDefaults;
|
||||
_initialValues = [initialValues copy];
|
||||
_appliesImmediately = YES;
|
||||
_valueProxy = [[_CPUserDefaultsControllerProxy alloc] initWithController:self];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)values
|
||||
{
|
||||
return _valueProxy;
|
||||
}
|
||||
|
||||
- (BOOL)hasUnappliedChanges
|
||||
{
|
||||
return [_valueProxy hasUnappliedChanges];
|
||||
}
|
||||
|
||||
- (void)save:(id)sender
|
||||
{
|
||||
[_valueProxy save];
|
||||
}
|
||||
|
||||
- (void)revert:(id)sender
|
||||
{
|
||||
[_valueProxy revert];
|
||||
}
|
||||
|
||||
- (void)revertToInitialValues:(id)sender
|
||||
{
|
||||
[_valueProxy revertToInitialValues];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
var CPUserDefaultsControllerSharedKey = "CPUserDefaultsControllerSharedKey";
|
||||
|
||||
@implementation CPUserDefaultsController (CPCoding)
|
||||
|
||||
- (id)initWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
if ([aCoder decodeBoolForKey:CPUserDefaultsControllerSharedKey])
|
||||
return [CPUserDefaultsController sharedUserDefaultsController];
|
||||
|
||||
self = [super initWithCoder:aCoder];
|
||||
|
||||
if (self)
|
||||
{
|
||||
[CPException raise:CPUnsupportedMethodException reason:@"decoding of non-shared CPUserDefaultsController not implemented"];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(CPCoder)aCoder
|
||||
{
|
||||
[super encodeWithCoder:aCoder];
|
||||
|
||||
if (self === SharedUserDefaultsController)
|
||||
{
|
||||
[aCoder encodeBool:YES forKey:CPUserDefaultsControllerSharedKey];
|
||||
return;
|
||||
}
|
||||
|
||||
[CPException raise:CPUnsupportedMethodException reason:@"encoding of non-shared CPUserDefaultsController not implemented"];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation _CPUserDefaultsControllerProxy : CPObject
|
||||
{
|
||||
CPUserDefaultsController _controller;
|
||||
// TODO Could be optimised with a JS dict.
|
||||
CPMutableDictionary _cachedValues;
|
||||
}
|
||||
|
||||
- (id)initWithController:(CPUserDefaultsController)aController
|
||||
{
|
||||
if (self = [super init])
|
||||
{
|
||||
_controller = aController;
|
||||
_cachedValues = [CPMutableDictionary dictionary];
|
||||
|
||||
[[CPNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:CPUserDefaultsDidChangeNotification object:[_controller defaults]];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
// FIXME No dealloc in Cappuccino.
|
||||
[[CPNotificationCenter defaultCenter] removeObserver:self];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (id)valueForKey:(CPString)aKey
|
||||
{
|
||||
var value = [_cachedValues objectForKey:aKey];
|
||||
if (value === nil)
|
||||
{
|
||||
value = [[_controller defaults] objectForKey:aKey];
|
||||
if (value === nil)
|
||||
value = [[_controller initialValues] objectForKey:aKey];
|
||||
|
||||
if (value !== nil)
|
||||
[_cachedValues setObject:value forKey:aKey];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
- (void)setValue:(id)aValue forKey:(CPString)aKey
|
||||
{
|
||||
[self willChangeValueForKey:aKey];
|
||||
[_cachedValues setObject:aValue forKey:aKey];
|
||||
if ([_controller appliesImmediately])
|
||||
[[_controller defaults] setObject:aValue forKey:aKey];
|
||||
[self didChangeValueForKey:aKey];
|
||||
}
|
||||
|
||||
|
||||
- (void)revert
|
||||
{
|
||||
var keys = [_cachedValues allKeys],
|
||||
keysCount = [keys count];
|
||||
|
||||
while(keysCount--)
|
||||
{
|
||||
var key = keys[keysCount];
|
||||
[self willChangeValueForKey:key];
|
||||
[_cachedValues removeObjectForKey:key];
|
||||
[self didChangeValueForKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)save
|
||||
{
|
||||
var keys = [_cachedValues allKeys],
|
||||
keysCount = [keys count];
|
||||
|
||||
while(keysCount--)
|
||||
{
|
||||
var key = keys[keysCount];
|
||||
[[_controller defaults] setObject:[_cachedValues objectForKey:key] forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)revertToInitialValues
|
||||
{
|
||||
var initial = [_controller initialValues],
|
||||
keys = [_cachedValues allKeys],
|
||||
keysCount = [keys count];
|
||||
|
||||
while(keysCount--)
|
||||
{
|
||||
var key = keys[keysCount];
|
||||
[self willChangeValueForKey:key];
|
||||
|
||||
var initialValue = [initial objectForKey:key];
|
||||
if (initialValue !== nil)
|
||||
[_cachedValues setObject:initialValue forKey:key];
|
||||
else
|
||||
[_cachedValues removeObjectForKey:key];
|
||||
|
||||
[self didChangeValueForKey:key];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (void)userDefaultsDidChange:(CPNotification)aNotification
|
||||
{
|
||||
var defaults = [_controller defaults],
|
||||
keys = [_cachedValues allKeys],
|
||||
keysCount = [keys count];
|
||||
|
||||
while(keysCount--)
|
||||
{
|
||||
var key = keys[keysCount],
|
||||
value = [_cachedValues objectForKey:key],
|
||||
newValue = [defaults objectForKey:key];
|
||||
|
||||
if (![value isEqual:newValue])
|
||||
{
|
||||
[self willChangeValueForKey:key];
|
||||
[_cachedValues setObject:newValue forKey:key];
|
||||
[self didChangeValueForKey:key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasUnappliedChanges
|
||||
{
|
||||
var defaults = [_controller defaults],
|
||||
keys = [_cachedValues allKeys],
|
||||
keysCount = [keys count];
|
||||
|
||||
while(keysCount--)
|
||||
{
|
||||
var key = keys[keysCount],
|
||||
value = [_cachedValues objectForKey:key],
|
||||
newValue = [defaults objectForKey:key];
|
||||
|
||||
if (![value isEqual:newValue])
|
||||
return YES;
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user