PageRenderTime 75ms CodeModel.GetById 25ms RepoModel.GetById 2ms app.codeStats 0ms

/MapView/Map/RMLayerCollection.m

http://github.com/route-me/route-me
Objective C | 240 lines | 176 code | 28 blank | 36 comment | 24 complexity | 521e8baca647deef1b993710bf45c1ef MD5 | raw file
  1. //
  2. // RMLayerSet.m
  3. //
  4. // Copyright (c) 2008-2009, Route-Me Contributors
  5. // All rights reserved.
  6. //
  7. // Redistribution and use in source and binary forms, with or without
  8. // modification, are permitted provided that the following conditions are met:
  9. //
  10. // * Redistributions of source code must retain the above copyright notice, this
  11. // list of conditions and the following disclaimer.
  12. // * Redistributions in binary form must reproduce the above copyright notice,
  13. // this list of conditions and the following disclaimer in the documentation
  14. // and/or other materials provided with the distribution.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17. // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  20. // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  23. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  24. // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  25. // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  26. // POSSIBILITY OF SUCH DAMAGE.
  27. #import "RMLayerCollection.h"
  28. #import "RMMapContents.h"
  29. #import "RMMercatorToScreenProjection.h"
  30. #import "RMMarker.h"
  31. @implementation RMLayerCollection
  32. - (id)initForContents: (RMMapContents *)_contents
  33. {
  34. if (![super init])
  35. return nil;
  36. sublayers = [[NSMutableArray alloc] init];
  37. mapContents = _contents;
  38. self.masksToBounds = YES;
  39. rotationTransform = CGAffineTransformIdentity;
  40. return self;
  41. }
  42. - (void) dealloc
  43. {
  44. [sublayers release];
  45. sublayers = nil;
  46. mapContents = nil;
  47. [super dealloc];
  48. }
  49. - (void)correctScreenPosition: (CALayer *)layer
  50. {
  51. if ([layer conformsToProtocol:@protocol(RMMovingMapLayer)])
  52. {
  53. // Kinda ugly.
  54. CALayer<RMMovingMapLayer>* layer_with_proto = (CALayer<RMMovingMapLayer>*)layer;
  55. if(layer_with_proto.enableDragging){
  56. RMProjectedPoint location = [layer_with_proto projectedLocation];
  57. layer_with_proto.position = [[mapContents mercatorToScreenProjection] projectXYPoint:location];
  58. }
  59. if(!layer_with_proto.enableRotation){
  60. [layer_with_proto setAffineTransform:rotationTransform];
  61. }
  62. }
  63. }
  64. - (void)setSublayers: (NSArray*)array
  65. {
  66. for (CALayer *layer in array)
  67. {
  68. [self correctScreenPosition:layer];
  69. }
  70. @synchronized(sublayers) {
  71. [sublayers removeAllObjects];
  72. [sublayers addObjectsFromArray:array];
  73. [super setSublayers:array];
  74. }
  75. }
  76. - (void)addSublayer:(CALayer *)layer
  77. {
  78. @synchronized(sublayers) {
  79. [self correctScreenPosition:layer];
  80. [sublayers addObject:layer];
  81. [super addSublayer:layer];
  82. }
  83. }
  84. - (void)removeSublayer:(CALayer *)layer
  85. {
  86. @synchronized(sublayers) {
  87. [sublayers removeObject:layer];
  88. [layer removeFromSuperlayer];
  89. }
  90. }
  91. - (void)removeSublayers:(NSArray *)layers
  92. {
  93. @synchronized(sublayers) {
  94. for(CALayer *aLayer in layers)
  95. {
  96. [sublayers removeObject:aLayer];
  97. [aLayer removeFromSuperlayer];
  98. }
  99. }
  100. }
  101. - (void)insertSublayer:(CALayer *)layer above:(CALayer *)siblingLayer
  102. {
  103. @synchronized(sublayers) {
  104. [self correctScreenPosition:layer];
  105. NSUInteger index = [sublayers indexOfObject:siblingLayer];
  106. [sublayers insertObject:layer atIndex:index + 1];
  107. [super insertSublayer:layer above:siblingLayer];
  108. }
  109. }
  110. - (void)insertSublayer:(CALayer *)layer below:(CALayer *)siblingLayer
  111. {
  112. @synchronized(sublayers) {
  113. [self correctScreenPosition:layer];
  114. NSUInteger index = [sublayers indexOfObject:siblingLayer];
  115. [sublayers insertObject:layer atIndex:index];
  116. [super insertSublayer:layer below:siblingLayer];
  117. }
  118. }
  119. - (void)insertSublayer:(CALayer *)layer atIndex:(unsigned)index
  120. {
  121. @synchronized(sublayers) {
  122. [self correctScreenPosition:layer];
  123. [sublayers insertObject:layer atIndex:index];
  124. [super insertSublayer:layer atIndex:index];
  125. }
  126. }
  127. /*
  128. - (void)insertSublayer:(RMMapLayer*) layer below:(RMMapLayer*)sibling;
  129. - (void)insertSublayer:(RMMapLayer*) layer above:(RMMapLayer*)sibling;
  130. - (void)removeSublayer:(RMMapLayer*) layer;
  131. */
  132. - (void)moveToProjectedPoint: (RMProjectedPoint)aPoint
  133. {
  134. /// \bug TODO: Test this. Does it work?
  135. [self correctPositionOfAllSublayers];
  136. }
  137. - (void)moveBy: (CGSize) delta
  138. {
  139. @synchronized(sublayers) {
  140. for (id layer in sublayers)
  141. {
  142. if ([layer respondsToSelector:@selector(moveBy:)])
  143. [layer moveBy:delta];
  144. // if layer moves on and offscreen...
  145. }
  146. }
  147. }
  148. - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center
  149. {
  150. @synchronized(sublayers) {
  151. for (id layer in sublayers)
  152. {
  153. if ([layer respondsToSelector:@selector(zoomByFactor:near:)])
  154. [layer zoomByFactor:zoomFactor near:center];
  155. }
  156. }
  157. }
  158. - (void) correctPositionOfAllSublayers
  159. {
  160. @synchronized(sublayers) {
  161. for (id layer in sublayers)
  162. {
  163. [self correctScreenPosition:layer];
  164. }
  165. }
  166. }
  167. - (BOOL) hasSubLayer:(CALayer *)layer
  168. {
  169. return [sublayers containsObject:layer];
  170. }
  171. - (void) setRotationOfAllSublayers:(float) angle
  172. {
  173. rotationTransform = CGAffineTransformMakeRotation(angle); // store rotation transform for subsequent layers
  174. @synchronized(sublayers) {
  175. for (id layer in sublayers)
  176. {
  177. CALayer<RMMovingMapLayer>* layer_with_proto = (CALayer<RMMovingMapLayer>*)layer;
  178. if(!layer_with_proto.enableRotation){
  179. [layer_with_proto setAffineTransform:rotationTransform];
  180. }
  181. }
  182. }
  183. }
  184. NSInteger layerSort(id num1, id num2, void *context) {
  185. if ([num1 isKindOfClass:[RMMarker class]] && [num2 isKindOfClass:[RMMarker class]]) {
  186. // if both are markers, order based on vertical map position
  187. RMMarker *first = (RMMarker *)num1;
  188. RMMarker *second = (RMMarker *)num2;
  189. double firstPos = first.projectedLocation.northing;
  190. double secondPos = second.projectedLocation.northing;
  191. if (firstPos > secondPos) {
  192. return NSOrderedAscending;
  193. } else if (firstPos < secondPos) {
  194. return NSOrderedDescending;
  195. } else {
  196. return NSOrderedSame;
  197. }
  198. } else {
  199. // if something isnt a marker, send to bottom
  200. if ([num1 isKindOfClass:[RMMarker class]]) {
  201. return NSOrderedDescending;
  202. } else if ([num2 isKindOfClass:[RMMarker class]]) {
  203. return NSOrderedAscending;
  204. } else {
  205. return NSOrderedSame;
  206. }
  207. }
  208. }
  209. - (void)orderLayers {
  210. self.sublayers = [self.sublayers sortedArrayUsingFunction:layerSort context:NULL];
  211. }
  212. @end