API  0.9.8
 All Classes Files Functions Variables Typedefs Macros Groups Pages
CPCib.j
Go to the documentation of this 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 
24 
25 CPCibOwner = @"CPCibOwner";
26 CPCibTopLevelObjects = @"CPCibTopLevelObjects";
27 CPCibReplacementClasses = @"CPCibReplacementClasses";
28 CPCibExternalObjects = @"CPCibExternalObjects";
29 
30 var CPCibObjectDataKey = @"CPCibObjectDataKey";
31 
36 @implementation CPCib : CPObject
37 {
38  CPData _data;
39  CPBundle _bundle;
40  BOOL _awakenCustomResources;
41 
42  id _loadDelegate;
43 }
44 
45 - (id)initWithContentsOfURL:(CPURL)aURL
46 {
47  self = [super init];
48 
49  if (self)
50  {
52 
53  if (!_data)
54  return nil;
55 
56  _awakenCustomResources = YES;
57  }
58 
59  return self;
60 }
61 
62 - (id)initWithContentsOfURL:(CPURL)aURL loadDelegate:(id)aLoadDelegate
63 {
64  self = [super init];
65 
66  if (self)
67  {
69 
70  _awakenCustomResources = YES;
71 
72  _loadDelegate = aLoadDelegate;
73  }
74 
75  return self;
76 }
77 
78 - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle
79 {
80  if (![aName hasSuffix:@".cib"])
81  aName = [aName stringByAppendingString:@".cib"];
82 
83  // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
84  self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]];
85 
86  if (self)
87  _bundle = aBundle;
88 
89  return self;
90 }
91 
92 - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
93 {
94  if (![aName hasSuffix:@".cib"])
95  aName = [aName stringByAppendingString:@".cib"];
96 
97  // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
98  self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate];
99 
100  if (self)
101  _bundle = aBundle;
102 
103  return self;
104 }
105 
106 - (void)_setAwakenCustomResources:(BOOL)shouldAwakenCustomResources
107 {
108  _awakenCustomResources = shouldAwakenCustomResources;
109 }
110 
111 - (BOOL)_awakenCustomResources
112 {
113  return _awakenCustomResources;
114 }
115 
116 - (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable
117 {
118  var bundle = _bundle,
119  owner = [anExternalNameTable objectForKey:CPCibOwner];
120 
121  if (!bundle && owner)
122  bundle = [CPBundle bundleForClass:[owner class]];
123 
124  var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources],
125  replacementClasses = [anExternalNameTable objectForKey:CPCibReplacementClasses];
126 
127  if (replacementClasses)
128  {
129  var key = nil,
130  keyEnumerator = [replacementClasses keyEnumerator];
131 
132  while ((key = [keyEnumerator nextObject]) !== nil)
133  [unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
134  }
135 
136  [unarchiver setExternalObjectsForProxyIdentifiers:[anExternalNameTable objectForKey:CPCibExternalObjects]];
137 
138  var objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey];
139 
140  if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
141  return NO;
142 
143  var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
144 
145  [objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
146  [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
147  [objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
148 
149  // Display Visible Windows.
150  [objectData displayVisibleWindows];
151 
152  return YES;
153 }
154 
155 - (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects
156 {
157  // anOwner can be nil, and we can't store nil in a dictionary. If we leave it out,
158  // anyone who asks for CPCibOwner will get nil back.
159  var nameTable = @{ CPCibTopLevelObjects: topLevelObjects };
160 
161  if (anOwner)
162  [nameTable setObject:anOwner forKey:CPCibOwner];
163 
164  return [self instantiateCibWithExternalNameTable:nameTable];
165 }
166 
167 @end
168 
170 
171 - (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data
172 {
173  // FIXME: Why aren't we getting connection:didFailWithError:
174  if (!data)
175  return [self connection:aConnection didFailWithError:nil];
176 
177  _data = [CPData dataWithRawString:data];
178 }
179 
180 - (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
181 {
182  if ([_loadDelegate respondsToSelector:@selector(cibDidFailToLoad:)])
183  [_loadDelegate cibDidFailToLoad:self];
184 
185  _loadDelegate = nil;
186 }
187 
188 - (void)connectionDidFinishLoading:(CPURLConnection)aConnection
189 {
190  if ([_loadDelegate respondsToSelector:@selector(cibDidFinishLoading:)])
191  [_loadDelegate cibDidFinishLoading:self];
192 
193  _loadDelegate = nil;
194 }
195 
196 @end
197 
198 var CPCibDataFileKey = @"CPCibDataFileKey",
199  CPCibBundleIdentifierKey = @"CPCibBundleIdentifierKey";
200 
201 @implementation CPCib (CPCoding)
202 
203 - (id)initWithCoder:(CPCoder)aCoder
204 {
205  self = [super init];
206 
207  var base64 = [aCoder decodeObjectForKey:CPCibDataFileKey];
208  _data = [CPData dataWithBase64:base64];
209 
210  return self;
211 }
212 
213 - (void)encodeWithCoder:(CPCoder)aCoder
214 {
215  [aCoder encodeObject:[_data base64] forKey:CPCibDataFileKey];
216 }
217 
218 @end