PageRenderTime 13ms CodeModel.GetById 1ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 1ms

/AppKit/Cib/CPCib.j

http://github.com/cacaodev/cappuccino
Unknown | 229 lines | 171 code | 58 blank | 0 comment | 0 complexity | 540694fe73cbe257bb0b879325a7a6a7 MD5 | raw file
  1/*
  2 * CPCib.j
  3 * AppKit
  4 *
  5 * Created by Francisco Tolmasky.
  6 * Copyright 2008, 280 North, Inc.
  7 *
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation; either
 11 * version 2.1 of the License, or (at your option) any later version.
 12 *
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 16 * Lesser General Public License for more details.
 17 *
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 21 */
 22
 23@import <Foundation/CPObject.j>
 24@import <Foundation/CPURLConnection.j>
 25@import <Foundation/CPURLRequest.j>
 26
 27@import "_CPCibClassSwapper.j"
 28@import "_CPCibCustomObject.j"
 29@import "_CPCibCustomResource.j"
 30@import "_CPCibCustomView.j"
 31@import "_CPCibKeyedUnarchiver.j"
 32@import "_CPCibObjectData.j"
 33@import "_CPCibProxyObject.j"
 34@import "_CPCibWindowTemplate.j"
 35
 36CPCibOwner              = @"CPCibOwner";
 37CPCibTopLevelObjects    = @"CPCibTopLevelObjects";
 38CPCibReplacementClasses = @"CPCibReplacementClasses";
 39CPCibExternalObjects    = @"CPCibExternalObjects";
 40
 41var CPCibObjectDataKey  = @"CPCibObjectDataKey";
 42
 43/*!
 44    @ingroup appkit
 45*/
 46
 47@implementation CPCib : CPObject
 48{
 49    CPData      _data;
 50    CPBundle    _bundle;
 51    BOOL        _awakenCustomResources;
 52
 53    id          _loadDelegate;
 54}
 55
 56- (id)initWithContentsOfURL:(CPURL)aURL
 57{
 58    self = [super init];
 59
 60    if (self)
 61    {
 62        _data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil];
 63
 64        if (!_data)
 65            return nil;
 66
 67        _awakenCustomResources = YES;
 68    }
 69
 70    return self;
 71}
 72
 73- (id)initWithContentsOfURL:(CPURL)aURL loadDelegate:(id)aLoadDelegate
 74{
 75    self = [super init];
 76
 77    if (self)
 78    {
 79        [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:aURL] delegate:self];
 80
 81        _awakenCustomResources = YES;
 82
 83        _loadDelegate = aLoadDelegate;
 84    }
 85
 86    return self;
 87}
 88
 89- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle
 90{
 91    if (![aName hasSuffix:@".cib"])
 92        aName = [aName stringByAppendingString:@".cib"];
 93
 94    // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
 95    self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]];
 96
 97    if (self)
 98        _bundle = aBundle;
 99
100    return self;
101}
102
103- (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
104{
105    if (![aName hasSuffix:@".cib"])
106        aName = [aName stringByAppendingString:@".cib"];
107
108    // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
109    self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate];
110
111    if (self)
112        _bundle = aBundle;
113
114    return self;
115}
116
117- (void)_setAwakenCustomResources:(BOOL)shouldAwakenCustomResources
118{
119    _awakenCustomResources = shouldAwakenCustomResources;
120}
121
122- (BOOL)_awakenCustomResources
123{
124    return _awakenCustomResources;
125}
126
127- (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable
128{
129    var bundle = _bundle,
130        owner = [anExternalNameTable objectForKey:CPCibOwner];
131
132    if (!bundle && owner)
133        bundle = [CPBundle bundleForClass:[owner class]];
134
135    var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources],
136        replacementClasses = [anExternalNameTable objectForKey:CPCibReplacementClasses];
137
138    if (replacementClasses)
139    {
140        var key = nil,
141            keyEnumerator = [replacementClasses keyEnumerator];
142
143        while ((key = [keyEnumerator nextObject]) !== nil)
144            [unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
145    }
146
147    [unarchiver setExternalObjectsForProxyIdentifiers:[anExternalNameTable objectForKey:CPCibExternalObjects]];
148
149    var objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey];
150
151    if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
152        return NO;
153
154    var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
155
156    [objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
157    [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
158    [objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
159
160    // Display Visible Windows.
161    [objectData displayVisibleWindows];
162
163    return YES;
164}
165
166- (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects
167{
168    // anOwner can be nil, and we can't store nil in a dictionary. If we leave it out,
169    // anyone who asks for CPCibOwner will get nil back.
170    var nameTable = @{ CPCibTopLevelObjects: topLevelObjects };
171
172    if (anOwner)
173        [nameTable setObject:anOwner forKey:CPCibOwner];
174
175    return [self instantiateCibWithExternalNameTable:nameTable];
176}
177
178@end
179
180@implementation CPCib (CPURLConnectionDelegate)
181
182- (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data
183{
184    // FIXME: Why aren't we getting connection:didFailWithError:
185    if (!data)
186        return [self connection:aConnection didFailWithError:nil];
187
188    _data = [CPData dataWithRawString:data];
189}
190
191- (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
192{
193    if ([_loadDelegate respondsToSelector:@selector(cibDidFailToLoad:)])
194        [_loadDelegate cibDidFailToLoad:self];
195
196    _loadDelegate = nil;
197}
198
199- (void)connectionDidFinishLoading:(CPURLConnection)aConnection
200{
201    if ([_loadDelegate respondsToSelector:@selector(cibDidFinishLoading:)])
202        [_loadDelegate cibDidFinishLoading:self];
203
204    _loadDelegate = nil;
205}
206
207@end
208
209var CPCibDataFileKey = @"CPCibDataFileKey",
210    CPCibBundleIdentifierKey = @"CPCibBundleIdentifierKey";
211
212@implementation CPCib (CPCoding)
213
214- (id)initWithCoder:(CPCoder)aCoder
215{
216    self = [super init];
217
218    var base64 = [aCoder decodeObjectForKey:CPCibDataFileKey];
219    _data = [CPData dataWithBase64:base64];
220
221    return self;
222}
223
224- (void)encodeWithCoder:(CPCoder)aCoder
225{
226    [aCoder encodeObject:[_data base64] forKey:CPCibDataFileKey];
227}
228
229@end