Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

MGLStyle key-value coding compliance #6097

Merged
merged 8 commits into from
Nov 29, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/mbgl/map/map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,13 @@ class Map : private util::noncopyable {
void removeAnnotation(AnnotationID);

// Sources
std::vector<style::Source*> getSources();
style::Source* getSource(const std::string& sourceID);
void addSource(std::unique_ptr<style::Source>);
std::unique_ptr<style::Source> removeSource(const std::string& sourceID);

// Layers
std::vector<style::Layer*> getLayers();
style::Layer* getLayer(const std::string& layerID);
void addLayer(std::unique_ptr<style::Layer>, const optional<std::string>& beforeLayerID = {});
std::unique_ptr<style::Layer> removeLayer(const std::string& layerID);
Expand Down
3 changes: 3 additions & 0 deletions platform/darwin/src/MGLBackgroundStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye
- (void)removeFromMapView:(MGLMapView *)mapView
{
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::BackgroundLayer> &>(removedLayer));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not part of this PR, but this cast is undefined behavior. You need to write something like:

template <class T, class U>
std::unique_ptr<T> dynamic_ptr_cast(std::unique_ptr<U> p) {
    T* t = dynamic_cast<T*>(p.get());
    if (!t) return nullptr;
    p.release();
    return t;
}

And be aware that this will return a null unique_ptr (and deallocate the input) if the dynamic_cast fails, i.e. if the input is not the anticipated derived type. In this particular code, it looks like this could happen if the user was aliasing *StyleLayer objects while at the same time removing a layer and adding another layer with the same identifier but a different layer type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#7211

_rawLayer = _pendingLayer.get();
}
Expand Down
3 changes: 3 additions & 0 deletions platform/darwin/src/MGLCircleStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye
- (void)removeFromMapView:(MGLMapView *)mapView
{
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::CircleLayer> &>(removedLayer));
_rawLayer = _pendingLayer.get();
}
Expand Down
3 changes: 3 additions & 0 deletions platform/darwin/src/MGLFillStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye
- (void)removeFromMapView:(MGLMapView *)mapView
{
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::FillLayer> &>(removedLayer));
_rawLayer = _pendingLayer.get();
}
Expand Down
7 changes: 7 additions & 0 deletions platform/darwin/src/MGLForegroundStyleLayer.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,11 @@ - (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)so
return self;
}

- (NSString *)description {
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; sourceIdentifier = %@; visible = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier,
self.sourceIdentifier, self.visible ? @"YES" : @"NO"];
}

@end
6 changes: 6 additions & 0 deletions platform/darwin/src/MGLGeoJSONSource.mm
Original file line number Diff line number Diff line change
Expand Up @@ -192,4 +192,10 @@ - (void)setFeatures:(NSArray *)features
_features = MGLFeaturesFromMBGLFeatures(featureCollection);
}

- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; features = %@>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.features];
}

@end
3 changes: 3 additions & 0 deletions platform/darwin/src/MGLLineStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye
- (void)removeFromMapView:(MGLMapView *)mapView
{
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::LineLayer> &>(removedLayer));
_rawLayer = _pendingLayer.get();
}
Expand Down
8 changes: 8 additions & 0 deletions platform/darwin/src/MGLRasterSource.mm
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,12 @@ - (void)removeFromMapView:(MGLMapView *)mapView
self.rawSource = _pendingSource.get();
}

- (NSString *)description
{
return [NSString stringWithFormat:
@"<%@: %p; identifier = %@; URL = %@; tileSet = %@; tileSize = %lu>",
NSStringFromClass([self class]), (void *)self, self.identifier, self.URL,
self.tileSet, (unsigned long)self.tileSize];
}

@end
3 changes: 3 additions & 0 deletions platform/darwin/src/MGLRasterStyleLayer.mm
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ - (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLaye
- (void)removeFromMapView:(MGLMapView *)mapView
{
auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
if (!removedLayer) {
return;
}
_pendingLayer = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::RasterLayer> &>(removedLayer));
_rawLayer = _pendingLayer.get();
}
Expand Down
27 changes: 27 additions & 0 deletions platform/darwin/src/MGLSource.mm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

#include <mbgl/style/source.hpp>

@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
Expand All @@ -12,4 +20,23 @@ - (instancetype)initWithIdentifier:(NSString *)identifier
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];
}

@end
98 changes: 67 additions & 31 deletions platform/darwin/src/MGLStyle.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
@interface MGLStyle : NSObject

#pragma mark Default Style URLs
#pragma mark Accessing Common Styles

/**
Returns the URL to version 8 of the
Expand Down Expand Up @@ -165,33 +165,61 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
+ (NSURL *)satelliteStreetsStyleURLWithVersion:(NSInteger)version;

#pragma mark Accessing Metadata About the Style

/**
The name of the style.

You can customize the style’s name in Mapbox Studio.
*/
@property (readonly, copy, nullable) NSString *name;

#pragma mark Runtime Styling
#pragma mark Managing Sources

/**
Returns a layer that conforms to `MGLStyleLayer` if any layer with the given
identifier was found.

@return An instance of a concrete subclass of `MGLStyleLayer` associated with
the given identifier.
A set containing the style’s sources.
*/
- (nullable MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier;

@property (nonatomic, strong) NS_MUTABLE_SET_OF(MGLSource *) *sources;

/**
Returns a source if any source with the given identifier was found.
Returns a source with the given identifier in the current style.

@return An instance of a concrete subclass of `MGLSource` associated with the
given identifier.
given identifier, or `nil` if the current style contains no such source.
*/
- (nullable MGLSource *)sourceWithIdentifier:(NSString *)identifier;

/**
Adds a new source to the current style.

@param source The source to add to the current style.
*/
- (void)addSource:(MGLSource *)source;

/**
Removes a source from the current style.

@param source The source to remove from the current style.
*/
- (void)removeSource:(MGLSource *)source;

#pragma mark Managing Style Layers

/**
The layers included in the style, arranged according to their front-to-back
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It may be somewhat heretical to arrange the layers array from front to back rather than back to front. But this is a very strong Cocoa convention (to the point that front is a synonym for first and back a synonym for last in AppleScript syntax). If there’s any confusion from developers familiar with the style specification, it’s outweighed by the confusion that developers familiar with Apple frameworks would experience otherwise. Hopefully my implementation is free of off-by-one errors, though. 😬

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.

@return An instance of a concrete subclass of `MGLStyleLayer` associated with
the given identifier, or `nil` if the current style contains no such style
layer.
*/
- (nullable MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier;

/**
Adds a new layer on top of existing layers.

Expand All @@ -201,34 +229,40 @@ static const NSInteger MGLStyleDefaultVersion = 9;
- (void)addLayer:(MGLStyleLayer *)layer;

/**
Inserts a new layer below another layer.

@param layer Layer to be inserted.
@param belowLayer A layer that's already on the map view.
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 belowLayer:(MGLStyleLayer *)otherLayer;
- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index;

/**
Removes a layer from the map view.
Inserts a new layer below another layer.

@param layer The layer object to remove from the map view. This object
must conform to the `MGLStyleLayer` protocol.
@param layer The layer to insert.
@param sibling An existing layer in the style.
*/
- (void)removeLayer:(MGLStyleLayer *)layer;
- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)sibling;

/**
Adds a new source to the map view.
Inserts a new layer above another layer.

@param source The source to add to the map view.
@param layer The layer to insert.
@param sibling An existing layer in the style.
*/
- (void)addSource:(MGLSource *)source;
- (void)insertLayer:(MGLStyleLayer *)layer aboveLayer:(MGLStyleLayer *)sibling;

/**
Removes a source from the map view.
Removes a layer from the map view.

@param source The source to remove.
@param layer The layer object to remove from the map view. This object
must conform to the `MGLStyleLayer` protocol.
*/
- (void)removeSource:(MGLSource *)source;
- (void)removeLayer:(MGLStyleLayer *)layer;

#pragma mark Managing Style Classes

/**
Currently active style classes, represented as an array of string identifiers.
Expand Down Expand Up @@ -258,12 +292,14 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
- (void)removeStyleClass:(NSString *)styleClass;

/**
Adds or overrides an image used by the style’s layers.

To use an image in a style layer, give it a unique name using this method,
then set the `iconImage` property of an `MGLSymbolStyleLayer` object to that name.
#pragma mark Managing a Style’s Images

/**
Adds or overrides an image used by the style’s layers.

To use an image in a style layer, give it a unique name using this method, then
set the `iconImage` property of an `MGLSymbolStyleLayer` object to that name.

@param image The image for the name.
@param name The name of the image to set to the style.
*/
Expand Down
Loading