From 850b70ff91e582916829c5248afcafa195070a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Thu, 18 Aug 2016 18:00:58 -0700 Subject: [core, ios, macos] Added layers and sources properties to MGLStyle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added new layers and sources properties to MGLStyle that contain all the style’s layers and sources, respectively. These properties are KVC-compliant with all the mutable to-many methods. Layers are ordered from topmost to bottommost, for consistency with Cocoa APIs where front/first means top and back/last means bottom. Also added storage for mbgl::style::Source in MGLSource proper for wrapping AnnotationSource. Until the style finishes loading, its name property is set to nil. Fixes #6003. --- platform/darwin/src/MGLBackgroundStyleLayer.mm | 3 + platform/darwin/src/MGLCircleStyleLayer.mm | 3 + platform/darwin/src/MGLFillStyleLayer.mm | 3 + platform/darwin/src/MGLLineStyleLayer.mm | 3 + platform/darwin/src/MGLRasterStyleLayer.mm | 3 + platform/darwin/src/MGLSource.mm | 22 +++ platform/darwin/src/MGLStyle.h | 35 ++++- platform/darwin/src/MGLStyle.mm | 198 +++++++++++++++++++++++-- platform/darwin/src/MGLStyleLayer.mm.ejs | 3 + platform/darwin/src/MGLSymbolStyleLayer.mm | 3 + platform/darwin/src/MGLVectorSource.mm | 2 - 11 files changed, 259 insertions(+), 19 deletions(-) (limited to 'platform/darwin') diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm index 883a6d139c..6e30a20c97 100644 --- a/platform/darwin/src/MGLBackgroundStyleLayer.mm +++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm @@ -51,6 +51,9 @@ - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 16f27991f8..aca8ff028c 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -83,6 +83,9 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 3a3b443849..d670fd31e9 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -78,6 +78,9 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index e367290416..34c58aa49a 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -90,6 +90,9 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm index b832b0ad29..49dc261be8 100644 --- a/platform/darwin/src/MGLRasterStyleLayer.mm +++ b/platform/darwin/src/MGLRasterStyleLayer.mm @@ -50,6 +50,9 @@ - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index 4f9cfb014f..2fa580df89 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -2,6 +2,14 @@ #include +@interface MGLSource () + +// Even though this class is abstract, MGLStyle uses it to represent some +// special internal source types like mbgl::AnnotationSource. +@property (nonatomic) mbgl::style::Source *rawSource; + +@end + @implementation MGLSource - (instancetype)initWithIdentifier:(NSString *)identifier @@ -12,6 +20,20 @@ return self; } +- (void)addToMapView:(MGLMapView *)mapView { + [NSException raise:NSInvalidArgumentException format: + @"The source %@ cannot be added to the style. " + @"Make sure the source was created as a member of a concrete subclass of MGLSource.", + self]; +} + +- (void)removeFromMapView:(MGLMapView *)mapView { + [NSException raise:NSInvalidArgumentException format: + @"The source %@ cannot be removed from the style. " + @"Make sure the source was created as a member of a concrete subclass of MGLSource.", + self]; +} + - (NSString *)description { return [NSString stringWithFormat:@"<%@: %p; identifier = %@>", NSStringFromClass([self class]), (void *)self, self.identifier]; diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h index 96dc8fba49..b3e1b28eee 100644 --- a/platform/darwin/src/MGLStyle.h +++ b/platform/darwin/src/MGLStyle.h @@ -176,6 +176,11 @@ static const NSInteger MGLStyleDefaultVersion = 9; #pragma mark Managing Sources +/** + A set containing the style’s sources. + */ +@property (nonatomic, strong) NS_MUTABLE_SET_OF(MGLSource *) *sources; + /** Returns a source with the given identifier in the current style. @@ -200,6 +205,12 @@ static const NSInteger MGLStyleDefaultVersion = 9; #pragma mark Managing Style Layers +/** + The layers included in the style, arranged according to their front-to-back + ordering on the screen. + */ +@property (nonatomic, strong) NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *layers; + /** Returns a style layer with the given identifier in the current style. @@ -217,13 +228,31 @@ static const NSInteger MGLStyleDefaultVersion = 9; */ - (void)addLayer:(MGLStyleLayer *)layer; +/** + Inserts a new layer into the style at the given index. + + @param layer The layer to insert. + @param index The index at which to insert the layer. An index of 0 would send + the layer to the back; an index equal to the number of objects in the + `layers` property would bring the layer to the front. + */ +- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index; + /** Inserts a new layer below another layer. - @param layer Layer to be inserted. - @param belowLayer A layer that's already on the map view. + @param layer The layer to insert. + @param sibling An existing layer in the style. + */ +- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)sibling; + +/** + Inserts a new layer above another layer. + + @param layer The layer to insert. + @param sibling An existing layer in the style. */ -- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)otherLayer; +- (void)insertLayer:(MGLStyleLayer *)layer aboveLayer:(MGLStyleLayer *)sibling; /** Removes a layer from the map view. diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 69d76614c0..4169c7a5d3 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -101,7 +101,8 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Metadata - (NSString *)name { - return @(self.mapView.mbglMap->getStyleName().c_str()); + std::string name = self.mapView.mbglMap->getStyleName(); + return name.empty() ? nil : @(name.c_str()); } - (NSURL *)URL { @@ -110,13 +111,43 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Sources +- (NS_MUTABLE_SET_OF(MGLSource *) *)sources { + auto rawSources = self.mapView.mbglMap->getSources(); + NSMutableSet *sources = [NSMutableSet setWithCapacity:rawSources.size()]; + for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { + MGLSource *source = [self sourceFromMBGLSource:*rawSource]; + [sources addObject:source]; + } + return sources; +} + +- (void)setSources:(NS_MUTABLE_SET_OF(MGLSource *) *)sources { + for (MGLSource *source in self.sources) { + [self removeSource:source]; + } + for (MGLSource *source in sources) { + [self addSource:source]; + } +} + +- (NSUInteger)countOfSources { + auto rawSources = self.mapView.mbglMap->getSources(); + return rawSources.size(); +} + +- (MGLSource *)memberOfSources:(MGLSource *)object { + return [self sourceWithIdentifier:object.identifier]; +} + - (MGLSource *)sourceWithIdentifier:(NSString *)identifier { - auto mbglSource = self.mapView.mbglMap->getSource(identifier.UTF8String); - if (!mbglSource) { - return nil; - } + auto rawSource = self.mapView.mbglMap->getSource(identifier.UTF8String); + return rawSource ? [self sourceFromMBGLSource:rawSource] : nil; +} +- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)mbglSource { + NSString *identifier = @(mbglSource->getID().c_str()); + // TODO: Fill in options specific to the respective source classes // https://github.com/mapbox/mapbox-gl-native/issues/6584 MGLSource *source; @@ -160,13 +191,93 @@ static NSURL *MGLStyleURL_emerald; #pragma mark Style layers -- (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier +- (NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers { - auto mbglLayer = self.mapView.mbglMap->getLayer(identifier.UTF8String); - if (!mbglLayer) { + auto layers = self.mapView.mbglMap->getLayers(); + NSMutableArray *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()]; + for (auto layer = layers.rbegin(); layer != layers.rend(); ++layer) { + MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:*layer]; + [styleLayers addObject:styleLayer]; + } + return styleLayers; +} + +- (void)setLayers:(NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers { + for (MGLStyleLayer *layer in self.layers.reverseObjectEnumerator) { + [self removeLayer:layer]; + } + for (MGLStyleLayer *layer in layers.reverseObjectEnumerator) { + [self addLayer:layer]; + } +} + +- (NSUInteger)countOfLayers +{ + return self.mapView.mbglMap->getLayers().size(); +} + +- (MGLStyleLayer *)objectInLayersAtIndex:(NSUInteger)index +{ + auto layers = self.mapView.mbglMap->getLayers(); + if (index > layers.size() - 1) { + [NSException raise:NSRangeException + format:@"No style layer at index %lu.", (unsigned long)index]; return nil; } + auto layer = layers.at(layers.size() - 1 - index); + return [self layerFromMBGLLayer:layer]; +} + +- (void)getLayers:(MGLStyleLayer **)buffer range:(NSRange)inRange +{ + auto layers = self.mapView.mbglMap->getLayers(); + if (NSMaxRange(inRange) > layers.size()) { + [NSException raise:NSRangeException + format:@"Style layer range %@ is out of bounds.", NSStringFromRange(inRange)]; + } + NSUInteger i = 0; + for (auto layer = *(layers.rbegin() + inRange.location); i < inRange.length; ++layer, ++i) { + MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer]; + buffer[i] = styleLayer; + } +} + +- (void)insertObject:(MGLStyleLayer *)styleLayer inLayersAtIndex:(NSUInteger)index +{ + if (!styleLayer.rawLayer) { + [NSException raise:NSInvalidArgumentException format: + @"The style layer %@ cannot be inserted into the style. " + @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.", + styleLayer]; + } + auto layers = self.mapView.mbglMap->getLayers(); + if (index > layers.size()) { + [NSException raise:NSRangeException + format:@"Cannot insert style layer at out-of-bounds index %lu.", (unsigned long)index]; + } else if (index == 0) { + [styleLayer addToMapView:self.mapView]; + } else { + MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(layers.size() - index)]; + [styleLayer addToMapView:self.mapView belowLayer:sibling]; + } +} + +- (void)removeObjectFromLayersAtIndex:(NSUInteger)index +{ + auto layers = self.mapView.mbglMap->getLayers(); + if (index > layers.size() - 1) { + [NSException raise:NSRangeException + format:@"Cannot remove style layer at out-of-bounds index %lu.", (unsigned long)index]; + } + auto layer = layers.at(layers.size() - 1 - index); + self.mapView.mbglMap->removeLayer(layer->getID()); +} +- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer +{ + NSParameterAssert(mbglLayer); + + NSString *identifier = @(mbglLayer->getID().c_str()); MGLStyleLayer *styleLayer; if (auto fillLayer = mbglLayer->as()) { MGLSource *source = [self sourceWithIdentifier:@(fillLayer->getSourceID().c_str())]; @@ -195,6 +306,12 @@ static NSURL *MGLStyleURL_emerald; return styleLayer; } +- (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier +{ + auto mbglLayer = self.mapView.mbglMap->getLayer(identifier.UTF8String); + return mbglLayer ? [self layerFromMBGLLayer:mbglLayer] : nil; +} + - (void)removeLayer:(MGLStyleLayer *)layer { if (!layer.rawLayer) { @@ -217,7 +334,11 @@ static NSURL *MGLStyleURL_emerald; [layer addToMapView:self.mapView]; } -- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)otherLayer +- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index { + [self insertObject:layer inLayersAtIndex:index]; +} + +- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)sibling { if (!layer.rawLayer) { [NSException raise:NSInvalidArgumentException @@ -226,14 +347,58 @@ static NSURL *MGLStyleURL_emerald; @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.", layer]; } - if (!otherLayer.rawLayer) { + if (!sibling.rawLayer) { + [NSException raise:NSInvalidArgumentException + format: + @"A style layer cannot be placed below %@ in the style. " + @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].", + sibling]; + } + [self willChangeValueForKey:@"layers"]; + [layer addToMapView:self.mapView belowLayer:sibling]; + [self didChangeValueForKey:@"layers"]; +} + +- (void)insertLayer:(MGLStyleLayer *)layer aboveLayer:(MGLStyleLayer *)sibling { + if (!layer.rawLayer) { + [NSException raise:NSInvalidArgumentException + format: + @"The style layer %@ cannot be added to the style. " + @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.", + layer]; + } + if (!sibling.rawLayer) { [NSException raise:NSInvalidArgumentException format: - @"A style layer cannot be placed before %@ in the style. " - @"Make sure otherLayer was obtained using -[MGLStyle layerWithIdentifier:].", - otherLayer]; + @"A style layer cannot be placed above %@ in the style. " + @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].", + sibling]; } - [layer addToMapView:self.mapView belowLayer:otherLayer]; + + auto layers = self.mapView.mbglMap->getLayers(); + std::string siblingIdentifier = sibling.identifier.UTF8String; + NSUInteger index = 0; + for (auto layer : layers) { + if (layer->getID() == siblingIdentifier) { + break; + } + index++; + } + + [self willChangeValueForKey:@"layers"]; + if (index + 1 > layers.size()) { + [NSException raise:NSInvalidArgumentException + format: + @"A style layer cannot be placed above %@ in the style. " + @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].", + sibling]; + } else if (index + 1 == layers.size()) { + [layer addToMapView:self.mapView]; + } else { + MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(index + 1)]; + [layer addToMapView:self.mapView belowLayer:sibling]; + } + [self didChangeValueForKey:@"layers"]; } #pragma mark Style classes @@ -270,6 +435,11 @@ static NSURL *MGLStyleURL_emerald; self.mapView.mbglMap->setClasses(newAppliedClasses); } +- (NSUInteger)countOfStyleClasses { + const auto &classes = self.mapView.mbglMap->getClasses(); + return classes.size(); +} + - (BOOL)hasStyleClass:(NSString *)styleClass { return styleClass && self.mapView.mbglMap->hasClass([styleClass UTF8String]); diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index f8b8305616..8febd69a20 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -120,6 +120,9 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_castLayer> &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index 9ba1bd7bc2..0acc36d2dc 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -137,6 +137,9 @@ namespace mbgl { - (void)removeFromMapView:(MGLMapView *)mapView { auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String); + if (!removedLayer) { + return; + } _pendingLayer = std::move(reinterpret_cast &>(removedLayer)); _rawLayer = _pendingLayer.get(); } diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index 1b3406e5e6..ae69456b45 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -18,8 +18,6 @@ std::unique_ptr _pendingSource; } -static NSString *MGLVectorSourceType = @"vector"; - - (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url { if (self = [super initWithIdentifier:identifier]) -- cgit v1.2.1