/MapView/Map/RMLayerCollection.m
Objective C | 240 lines | 176 code | 28 blank | 36 comment | 24 complexity | 521e8baca647deef1b993710bf45c1ef MD5 | raw file
- //
- // RMLayerSet.m
- //
- // Copyright (c) 2008-2009, Route-Me Contributors
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or without
- // modification, are permitted provided that the following conditions are met:
- //
- // * Redistributions of source code must retain the above copyright notice, this
- // list of conditions and the following disclaimer.
- // * Redistributions in binary form must reproduce the above copyright notice,
- // this list of conditions and the following disclaimer in the documentation
- // and/or other materials provided with the distribution.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
- // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- // POSSIBILITY OF SUCH DAMAGE.
- #import "RMLayerCollection.h"
- #import "RMMapContents.h"
- #import "RMMercatorToScreenProjection.h"
- #import "RMMarker.h"
- @implementation RMLayerCollection
- - (id)initForContents: (RMMapContents *)_contents
- {
- if (![super init])
- return nil;
- sublayers = [[NSMutableArray alloc] init];
- mapContents = _contents;
- self.masksToBounds = YES;
- rotationTransform = CGAffineTransformIdentity;
- return self;
- }
- - (void) dealloc
- {
- [sublayers release];
- sublayers = nil;
- mapContents = nil;
- [super dealloc];
- }
- - (void)correctScreenPosition: (CALayer *)layer
- {
- if ([layer conformsToProtocol:@protocol(RMMovingMapLayer)])
- {
- // Kinda ugly.
- CALayer<RMMovingMapLayer>* layer_with_proto = (CALayer<RMMovingMapLayer>*)layer;
- if(layer_with_proto.enableDragging){
- RMProjectedPoint location = [layer_with_proto projectedLocation];
- layer_with_proto.position = [[mapContents mercatorToScreenProjection] projectXYPoint:location];
- }
- if(!layer_with_proto.enableRotation){
- [layer_with_proto setAffineTransform:rotationTransform];
- }
- }
- }
- - (void)setSublayers: (NSArray*)array
- {
- for (CALayer *layer in array)
- {
- [self correctScreenPosition:layer];
- }
- @synchronized(sublayers) {
- [sublayers removeAllObjects];
- [sublayers addObjectsFromArray:array];
- [super setSublayers:array];
- }
- }
- - (void)addSublayer:(CALayer *)layer
- {
- @synchronized(sublayers) {
- [self correctScreenPosition:layer];
- [sublayers addObject:layer];
- [super addSublayer:layer];
- }
- }
- - (void)removeSublayer:(CALayer *)layer
- {
- @synchronized(sublayers) {
- [sublayers removeObject:layer];
- [layer removeFromSuperlayer];
- }
- }
- - (void)removeSublayers:(NSArray *)layers
- {
- @synchronized(sublayers) {
- for(CALayer *aLayer in layers)
- {
- [sublayers removeObject:aLayer];
- [aLayer removeFromSuperlayer];
- }
- }
- }
- - (void)insertSublayer:(CALayer *)layer above:(CALayer *)siblingLayer
- {
- @synchronized(sublayers) {
- [self correctScreenPosition:layer];
- NSUInteger index = [sublayers indexOfObject:siblingLayer];
- [sublayers insertObject:layer atIndex:index + 1];
- [super insertSublayer:layer above:siblingLayer];
- }
- }
- - (void)insertSublayer:(CALayer *)layer below:(CALayer *)siblingLayer
- {
- @synchronized(sublayers) {
- [self correctScreenPosition:layer];
- NSUInteger index = [sublayers indexOfObject:siblingLayer];
- [sublayers insertObject:layer atIndex:index];
- [super insertSublayer:layer below:siblingLayer];
- }
- }
- - (void)insertSublayer:(CALayer *)layer atIndex:(unsigned)index
- {
- @synchronized(sublayers) {
- [self correctScreenPosition:layer];
- [sublayers insertObject:layer atIndex:index];
- [super insertSublayer:layer atIndex:index];
- }
- }
- /*
- - (void)insertSublayer:(RMMapLayer*) layer below:(RMMapLayer*)sibling;
- - (void)insertSublayer:(RMMapLayer*) layer above:(RMMapLayer*)sibling;
- - (void)removeSublayer:(RMMapLayer*) layer;
- */
- - (void)moveToProjectedPoint: (RMProjectedPoint)aPoint
- {
- /// \bug TODO: Test this. Does it work?
- [self correctPositionOfAllSublayers];
- }
- - (void)moveBy: (CGSize) delta
- {
- @synchronized(sublayers) {
- for (id layer in sublayers)
- {
- if ([layer respondsToSelector:@selector(moveBy:)])
- [layer moveBy:delta];
- // if layer moves on and offscreen...
- }
- }
- }
- - (void)zoomByFactor: (float) zoomFactor near:(CGPoint) center
- {
- @synchronized(sublayers) {
- for (id layer in sublayers)
- {
- if ([layer respondsToSelector:@selector(zoomByFactor:near:)])
- [layer zoomByFactor:zoomFactor near:center];
- }
- }
- }
- - (void) correctPositionOfAllSublayers
- {
- @synchronized(sublayers) {
- for (id layer in sublayers)
- {
- [self correctScreenPosition:layer];
- }
- }
- }
- - (BOOL) hasSubLayer:(CALayer *)layer
- {
- return [sublayers containsObject:layer];
- }
- - (void) setRotationOfAllSublayers:(float) angle
- {
- rotationTransform = CGAffineTransformMakeRotation(angle); // store rotation transform for subsequent layers
- @synchronized(sublayers) {
- for (id layer in sublayers)
- {
- CALayer<RMMovingMapLayer>* layer_with_proto = (CALayer<RMMovingMapLayer>*)layer;
- if(!layer_with_proto.enableRotation){
- [layer_with_proto setAffineTransform:rotationTransform];
- }
- }
- }
- }
- NSInteger layerSort(id num1, id num2, void *context) {
- if ([num1 isKindOfClass:[RMMarker class]] && [num2 isKindOfClass:[RMMarker class]]) {
- // if both are markers, order based on vertical map position
- RMMarker *first = (RMMarker *)num1;
- RMMarker *second = (RMMarker *)num2;
- double firstPos = first.projectedLocation.northing;
- double secondPos = second.projectedLocation.northing;
- if (firstPos > secondPos) {
- return NSOrderedAscending;
- } else if (firstPos < secondPos) {
- return NSOrderedDescending;
- } else {
- return NSOrderedSame;
- }
- } else {
- // if something isnt a marker, send to bottom
- if ([num1 isKindOfClass:[RMMarker class]]) {
- return NSOrderedDescending;
- } else if ([num2 isKindOfClass:[RMMarker class]]) {
- return NSOrderedAscending;
- } else {
- return NSOrderedSame;
- }
- }
- }
- - (void)orderLayers {
- self.sublayers = [self.sublayers sortedArrayUsingFunction:layerSort context:NULL];
- }
- @end