/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. @import <Foundation/CPObject.j>
  23. @import <Foundation/CPURLConnection.j>
  24. @import <Foundation/CPURLRequest.j>
  25. @import "_CPCibClassSwapper.j"
  26. @import "_CPCibCustomObject.j"
  27. @import "_CPCibCustomResource.j"
  28. @import "_CPCibCustomView.j"
  29. @import "_CPCibKeyedUnarchiver.j"
  30. @import "_CPCibObjectData.j"
  31. @import "_CPCibProxyObject.j"
  32. @import "_CPCibWindowTemplate.j"
  33. CPCibOwner = @"CPCibOwner";
  34. CPCibTopLevelObjects = @"CPCibTopLevelObjects";
  35. CPCibReplacementClasses = @"CPCibReplacementClasses";
  36. CPCibExternalObjects = @"CPCibExternalObjects";
  37. var CPCibObjectDataKey = @"CPCibObjectDataKey";
  38. /*!
  39. @ingroup appkit
  40. */
  41. @implementation CPCib : CPObject
  42. {
  43. CPData _data;
  44. CPBundle _bundle;
  45. BOOL _awakenCustomResources;
  46. id _loadDelegate;
  47. }
  48. - (id)initWithContentsOfURL:(CPURL)aURL
  49. {
  50. self = [super init];
  51. if (self)
  52. {
  53. _data = [CPURLConnection sendSynchronousRequest:[CPURLRequest requestWithURL:aURL] returningResponse:nil];
  54. if (!_data)
  55. return nil;
  56. _awakenCustomResources = YES;
  57. }
  58. return self;
  59. }
  60. - (id)initWithContentsOfURL:(CPURL)aURL loadDelegate:(id)aLoadDelegate
  61. {
  62. self = [super init];
  63. if (self)
  64. {
  65. [CPURLConnection connectionWithRequest:[CPURLRequest requestWithURL:aURL] delegate:self];
  66. _awakenCustomResources = YES;
  67. _loadDelegate = aLoadDelegate;
  68. }
  69. return self;
  70. }
  71. - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle
  72. {
  73. if (![aName hasSuffix:@".cib"])
  74. aName = [aName stringByAppendingString:@".cib"];
  75. // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
  76. self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName]];
  77. if (self)
  78. _bundle = aBundle;
  79. return self;
  80. }
  81. - (id)initWithCibNamed:(CPString)aName bundle:(CPBundle)aBundle loadDelegate:(id)aLoadDelegate
  82. {
  83. if (![aName hasSuffix:@".cib"])
  84. aName = [aName stringByAppendingString:@".cib"];
  85. // If aBundle is nil, use mainBundle, but ONLY for searching for the nib, not for resources later.
  86. self = [self initWithContentsOfURL:[aBundle || [CPBundle mainBundle] pathForResource:aName] loadDelegate:aLoadDelegate];
  87. if (self)
  88. _bundle = aBundle;
  89. return self;
  90. }
  91. - (void)_setAwakenCustomResources:(BOOL)shouldAwakenCustomResources
  92. {
  93. _awakenCustomResources = shouldAwakenCustomResources;
  94. }
  95. - (BOOL)_awakenCustomResources
  96. {
  97. return _awakenCustomResources;
  98. }
  99. - (BOOL)instantiateCibWithExternalNameTable:(CPDictionary)anExternalNameTable
  100. {
  101. var bundle = _bundle,
  102. owner = [anExternalNameTable objectForKey:CPCibOwner];
  103. if (!bundle && owner)
  104. bundle = [CPBundle bundleForClass:[owner class]];
  105. var unarchiver = [[_CPCibKeyedUnarchiver alloc] initForReadingWithData:_data bundle:bundle awakenCustomResources:_awakenCustomResources],
  106. replacementClasses = [anExternalNameTable objectForKey:CPCibReplacementClasses];
  107. if (replacementClasses)
  108. {
  109. var key = nil,
  110. keyEnumerator = [replacementClasses keyEnumerator];
  111. while ((key = [keyEnumerator nextObject]) !== nil)
  112. [unarchiver setClass:[replacementClasses objectForKey:key] forClassName:key];
  113. }
  114. [unarchiver setExternalObjectsForProxyIdentifiers:[anExternalNameTable objectForKey:CPCibExternalObjects]];
  115. var objectData = [unarchiver decodeObjectForKey:CPCibObjectDataKey];
  116. if (!objectData || ![objectData isKindOfClass:[_CPCibObjectData class]])
  117. return NO;
  118. var topLevelObjects = [anExternalNameTable objectForKey:CPCibTopLevelObjects];
  119. [objectData instantiateWithOwner:owner topLevelObjects:topLevelObjects];
  120. [objectData establishConnectionsWithOwner:owner topLevelObjects:topLevelObjects];
  121. [objectData awakeWithOwner:owner topLevelObjects:topLevelObjects];
  122. // Display Visible Windows.
  123. [objectData displayVisibleWindows];
  124. return YES;
  125. }
  126. - (BOOL)instantiateCibWithOwner:(id)anOwner topLevelObjects:(CPArray)topLevelObjects
  127. {
  128. // anOwner can be nil, and we can't store nil in a dictionary. If we leave it out,
  129. // anyone who asks for CPCibOwner will get nil back.
  130. var nameTable = @{ CPCibTopLevelObjects: topLevelObjects };
  131. if (anOwner)
  132. [nameTable setObject:anOwner forKey:CPCibOwner];
  133. return [self instantiateCibWithExternalNameTable:nameTable];
  134. }
  135. @end
  136. @implementation CPCib (CPURLConnectionDelegate)
  137. - (void)connection:(CPURLConnection)aConnection didReceiveData:(CPString)data
  138. {
  139. // FIXME: Why aren't we getting connection:didFailWithError:
  140. if (!data)
  141. return [self connection:aConnection didFailWithError:nil];
  142. _data = [CPData dataWithRawString:data];
  143. }
  144. - (void)connection:(CPURLConnection)aConnection didFailWithError:(CPError)anError
  145. {
  146. if ([_loadDelegate respondsToSelector:@selector(cibDidFailToLoad:)])
  147. [_loadDelegate cibDidFailToLoad:self];
  148. _loadDelegate = nil;
  149. }
  150. - (void)connectionDidFinishLoading:(CPURLConnection)aConnection
  151. {
  152. if ([_loadDelegate respondsToSelector:@selector(cibDidFinishLoading:)])
  153. [_loadDelegate cibDidFinishLoading:self];
  154. _loadDelegate = nil;
  155. }
  156. @end
  157. var CPCibDataFileKey = @"CPCibDataFileKey",
  158. CPCibBundleIdentifierKey = @"CPCibBundleIdentifierKey";
  159. @implementation CPCib (CPCoding)
  160. - (id)initWithCoder:(CPCoder)aCoder
  161. {
  162. self = [super init];
  163. var base64 = [aCoder decodeObjectForKey:CPCibDataFileKey];
  164. _data = [CPData dataWithBase64:base64];
  165. return self;
  166. }
  167. - (void)encodeWithCoder:(CPCoder)aCoder
  168. {
  169. [aCoder encodeObject:[_data base64] forKey:CPCibDataFileKey];
  170. }
  171. @end