diff options
Diffstat (limited to 'platform/darwin/src')
-rw-r--r-- | platform/darwin/src/MGLAttributionInfo.h | 58 | ||||
-rw-r--r-- | platform/darwin/src/MGLAttributionInfo.mm | 178 | ||||
-rw-r--r-- | platform/darwin/src/MGLGeoJSONSource.mm | 6 | ||||
-rw-r--r-- | platform/darwin/src/MGLGeoJSONSource_Private.h | 3 | ||||
-rw-r--r-- | platform/darwin/src/MGLRasterSource.mm | 14 | ||||
-rw-r--r-- | platform/darwin/src/MGLRasterSource_Private.h | 13 | ||||
-rw-r--r-- | platform/darwin/src/MGLSource.mm | 8 | ||||
-rw-r--r-- | platform/darwin/src/MGLSource_Private.h | 12 | ||||
-rw-r--r-- | platform/darwin/src/MGLStyle.mm | 47 | ||||
-rw-r--r-- | platform/darwin/src/MGLStyle_Private.h | 5 | ||||
-rw-r--r-- | platform/darwin/src/MGLTileSet.h | 48 | ||||
-rw-r--r-- | platform/darwin/src/MGLTileSet.mm | 8 | ||||
-rw-r--r-- | platform/darwin/src/MGLTileSet_Private.h | 17 | ||||
-rw-r--r-- | platform/darwin/src/MGLVectorSource.mm | 14 | ||||
-rw-r--r-- | platform/darwin/src/MGLVectorSource_Private.h | 13 | ||||
-rw-r--r-- | platform/darwin/src/NSString+MGLAdditions.h | 13 | ||||
-rw-r--r-- | platform/darwin/src/NSString+MGLAdditions.m | 25 |
17 files changed, 434 insertions, 48 deletions
diff --git a/platform/darwin/src/MGLAttributionInfo.h b/platform/darwin/src/MGLAttributionInfo.h new file mode 100644 index 0000000000..c0cb1578b5 --- /dev/null +++ b/platform/darwin/src/MGLAttributionInfo.h @@ -0,0 +1,58 @@ +#import <Foundation/Foundation.h> +#import <CoreGraphics/CoreGraphics.h> +#import <CoreLocation/CoreLocation.h> + +#import "MGLTypes.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + Information about an attribution statement, usually a copyright or trademark + statement, associated with a map source. + */ +@interface MGLAttributionInfo : NSObject + +/** + Parses and returns the attribution infos contained in the given HTML source + code string. + + @param htmlString The HTML source code to parse. + @param fontSize The default text size in points. + @param linkColor The default link color. + */ ++ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + +- (instancetype)initWithTitle:(NSAttributedString *)title URL:(nullable NSURL *)URL; + +@property (nonatomic) NSAttributedString *title; +@property (nonatomic, nullable) NSURL *URL; +@property (nonatomic, getter=isFeedbackLink) BOOL feedbackLink; + +- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel; + +@end + +@interface NSMutableArray (MGLAttributionInfoAdditions) + +/** + Adds the given attribution info object to the receiver as long as it isn’t + redundant to any object already in the receiver. Any existing object that is + redundant to the given object is replaced by the given object. + + @param info The info object to add to the receiver. + @return True if the given info object was added to the receiver. + */ +- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info; + +/** + Adds each of the given attribution info objects to the receiver as long as it + isn’t redundant to any object already in the receiver. Any existing object that + is redundant to the given object is replaced by the given object. + + @param infos An array of info objects to add to the receiver. + */ +- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos; + +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm new file mode 100644 index 0000000000..2719aef7ca --- /dev/null +++ b/platform/darwin/src/MGLAttributionInfo.mm @@ -0,0 +1,178 @@ +#import "MGLAttributionInfo.h" + +#if TARGET_OS_IPHONE + #import <UIKit/UIKit.h> +#else + #import <Cocoa/Cocoa.h> +#endif + +#import "MGLMapCamera.h" +#import "NSString+MGLAdditions.h" + +#include <string> + +@implementation MGLAttributionInfo + ++ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { + NSDictionary *options = @{ + NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, + NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding), + }; + // Apply a bogus, easily detectable style rule to any feedback link, since + // NSAttributedString doesn’t preserve the class attribute. + NSMutableString *css = [NSMutableString stringWithString: + @".mapbox-improve-map { -webkit-text-stroke-width: 1000px; }"]; + if (fontSize) { + [css appendFormat:@"html { font-size: %.1fpx; }", fontSize]; + } + if (linkColor) { + CGFloat red; + CGFloat green; + CGFloat blue; + CGFloat alpha; +#if !TARGET_OS_IPHONE + linkColor = [linkColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace]; +#endif + [linkColor getRed:&red green:&green blue:&blue alpha:&alpha]; + [css appendFormat: + @"a:link { color: rgba(%f%%, %f%%, %f%%, %f); }", + red * 100, green * 100, blue * 100, alpha]; + } + NSString *styledHTML = [NSString stringWithFormat:@"<style type='text/css'>%@</style>%@", css, htmlString]; + NSData *htmlData = [styledHTML dataUsingEncoding:NSUTF8StringEncoding]; + +#if TARGET_OS_IPHONE + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:htmlData + options:options + documentAttributes:nil + error:NULL]; +#else + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithHTML:htmlData + options:options + documentAttributes:nil]; +#endif + + NSMutableArray *infos = [NSMutableArray array]; + [attributedString enumerateAttribute:NSLinkAttributeName + inRange:attributedString.mgl_wholeRange + options:0 + usingBlock: + ^(id _Nullable value, NSRange range, BOOL * _Nonnull stop) { + NSCAssert(!value || [value isKindOfClass:[NSURL class]], @"If present, URL attribute must be an NSURL."); + + // Detect feedback links by the bogus style rule applied above. + NSNumber *strokeWidth = [attributedString attribute:NSStrokeWidthAttributeName + atIndex:range.location + effectiveRange:NULL]; + BOOL isFeedbackLink = NO; + if ([strokeWidth floatValue] > 100) { + isFeedbackLink = YES; + [attributedString removeAttribute:NSStrokeWidthAttributeName range:range]; + } + + // Omit whitespace-only strings. + NSAttributedString *title = [[attributedString attributedSubstringFromRange:range] + mgl_attributedStringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if (!title.length) { + return; + } + + MGLAttributionInfo *info = [[MGLAttributionInfo alloc] initWithTitle:title URL:value]; + info.feedbackLink = isFeedbackLink; + [infos addObject:info]; + }]; + return infos; +} + +- (instancetype)initWithTitle:(NSAttributedString *)title URL:(NSURL *)URL { + if (self = [super init]) { + _title = title; + _URL = URL; + } + return self; +} + +- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel { + if (!self.feedbackLink) { + return nil; + } + + NSURLComponents *components = [NSURLComponents componentsWithURL:self.URL resolvingAgainstBaseURL:NO]; + components.fragment = [NSString stringWithFormat:@"/%.5f/%.5f/%i", + centerCoordinate.longitude, centerCoordinate.latitude, (int)round(zoomLevel + 1)]; + return components.URL; +} + +- (BOOL)isEqual:(id)object { + return [object isKindOfClass:[self class]] && [[object title] isEqual:self.title] && [[object URL] isEqual:self.URL]; +} + +- (NSUInteger)hash { + return self.title.hash + self.URL.hash; +} + +/** + Returns whether the given attribution info object overlaps with the receiver by + its plain text title. + + @return `NSOrderedAscending` if the given object is a superset of the receiver, + `NSOrderedDescending` if it is a subset of the receiver, or `NSOrderedSame` + if there is no overlap. + */ +- (NSComparisonResult)subsetCompare:(MGLAttributionInfo *)otherInfo { + NSString *title = self.title.string; + NSString *otherTitle = otherInfo.title.string; + if ([title containsString:otherTitle]) { + return NSOrderedDescending; + } + if ([otherTitle containsString:title]) { + return NSOrderedAscending; + } + return NSOrderedSame; +} + +@end + +@implementation NSMutableArray (MGLAttributionInfoAdditions) + +- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info { + __block BOOL didInsertInfo = NO; + __block BOOL shouldAddInfo = YES; + [self enumerateObjectsUsingBlock:^(MGLAttributionInfo * _Nonnull existingInfo, NSUInteger idx, BOOL * _Nonnull stop) { + switch ([info subsetCompare:existingInfo]) { + case NSOrderedDescending: + // The existing info object is a subset of the one we’re adding. + // Replace the existing object the first time we find a subset; + // remove the existing object every time after that. + if (didInsertInfo) { + [self removeObjectAtIndex:idx]; + } else { + [self replaceObjectAtIndex:idx withObject:info]; + didInsertInfo = YES; + } + break; + + case NSOrderedAscending: + // The info object we’re adding is a subset of the existing one. + // Don’t add the object and stop looking. + shouldAddInfo = NO; + *stop = YES; + break; + + default: + break; + } + }]; + if (shouldAddInfo && !didInsertInfo) { + // No overlapping infos were found, so append the info object. + [self addObject:info]; + } +} + +- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos { + for (MGLAttributionInfo *info in infos) { + [self growArrayByAddingAttributionInfo:info]; + } +} + +@end diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm index 7fd89ddc74..570b884149 100644 --- a/platform/darwin/src/MGLGeoJSONSource.mm +++ b/platform/darwin/src/MGLGeoJSONSource.mm @@ -18,6 +18,8 @@ const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"M @interface MGLGeoJSONSource () +- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource NS_DESIGNATED_INITIALIZER; + @property (nonatomic, readwrite) NSDictionary *options; @property (nonatomic) mbgl::style::GeoJSONSource *rawSource; @@ -60,6 +62,10 @@ const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"M return self; } +- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource { + return [super initWithRawSource:rawSource]; +} + - (void)addToMapView:(MGLMapView *)mapView { if (_pendingSource == nullptr) { diff --git a/platform/darwin/src/MGLGeoJSONSource_Private.h b/platform/darwin/src/MGLGeoJSONSource_Private.h index de5bb10fac..9d67deee34 100644 --- a/platform/darwin/src/MGLGeoJSONSource_Private.h +++ b/platform/darwin/src/MGLGeoJSONSource_Private.h @@ -1,10 +1,11 @@ #import "MGLGeoJSONSource.h" -#import "MGLGeoJSONSource_Private.h" #include <mbgl/style/sources/geojson_source.hpp> @interface MGLGeoJSONSource (Private) +- (instancetype)initWithRawSource:(mbgl::style::GeoJSONSource *)rawSource; + - (mbgl::style::GeoJSONOptions)geoJSONOptions; @end diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm index 62472050e3..1671e1decd 100644 --- a/platform/darwin/src/MGLRasterSource.mm +++ b/platform/darwin/src/MGLRasterSource.mm @@ -1,4 +1,4 @@ -#import "MGLRasterSource.h" +#import "MGLRasterSource_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" @@ -9,6 +9,8 @@ @interface MGLRasterSource () +- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource NS_DESIGNATED_INITIALIZER; + @property (nonatomic) mbgl::style::RasterSource *rawSource; @end @@ -39,6 +41,16 @@ return self; } +- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource { + if (self = [super initWithRawSource:rawSource]) { + if (auto attribution = rawSource->getAttribution()) { + _tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[]]; + _tileSet.attribution = @(attribution->c_str()); + } + } + return self; +} + - (void)commonInit { std::unique_ptr<mbgl::style::RasterSource> source; diff --git a/platform/darwin/src/MGLRasterSource_Private.h b/platform/darwin/src/MGLRasterSource_Private.h new file mode 100644 index 0000000000..4a367cf8f8 --- /dev/null +++ b/platform/darwin/src/MGLRasterSource_Private.h @@ -0,0 +1,13 @@ +#import "MGLRasterSource.h" + +namespace mbgl { + namespace style { + class RasterSource; + } +} + +@interface MGLRasterSource (Private) + +- (instancetype)initWithRawSource:(mbgl::style::RasterSource *)rawSource; + +@end diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm index 2fa580df89..c96b6c41c6 100644 --- a/platform/darwin/src/MGLSource.mm +++ b/platform/darwin/src/MGLSource.mm @@ -20,6 +20,14 @@ return self; } +- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource { + NSString *identifier = @(rawSource->getID().c_str()); + if (self = [self initWithIdentifier:identifier]) { + _rawSource = rawSource; + } + return self; +} + - (void)addToMapView:(MGLMapView *)mapView { [NSException raise:NSInvalidArgumentException format: @"The source %@ cannot be added to the style. " diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h index d360e71f3c..3100e0ae6e 100644 --- a/platform/darwin/src/MGLSource_Private.h +++ b/platform/darwin/src/MGLSource_Private.h @@ -1,13 +1,21 @@ #import "MGLSource.h" -#include <mbgl/mbgl.hpp> -#include <mbgl/style/source.hpp> +namespace mbgl { + namespace style { + class Source; + } +} @class MGLMapView; @interface MGLSource (Private) /** + Initializes and returns a source with a raw pointer to the backing store. + */ +- (instancetype)initWithRawSource:(mbgl::style::Source *)rawSource; + +/** A raw pointer to the mbgl object, which is always initialized, either to the value returned by `mbgl::Map getSource`, or for independently created objects, to the pointer value held in `pendingSource`. In the latter case, this raw diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index a6de4e798d..ee0bb286ba 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -17,10 +17,13 @@ #import "NSDate+MGLAdditions.h" #import "MGLSource.h" -#import "MGLVectorSource.h" +#import "MGLVectorSource_Private.h" #import "MGLRasterSource.h" #import "MGLGeoJSONSource.h" +#import "MGLAttributionInfo.h" +#import "MGLTileSet_Private.h" + #include <mbgl/util/default_styles.hpp> #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/style/layers/fill_layer.hpp> @@ -158,25 +161,18 @@ static NSURL *MGLStyleURL_emerald; return rawSource ? [self sourceFromMBGLSource:rawSource] : nil; } -- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)mbglSource { - NSString *identifier = @(mbglSource->getID().c_str()); - +- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)source { // TODO: Fill in options specific to the respective source classes // https://github.com/mapbox/mapbox-gl-native/issues/6584 - MGLSource *source; - if (mbglSource->is<mbgl::style::VectorSource>()) { - source = [[MGLVectorSource alloc] initWithIdentifier:identifier]; - } else if (mbglSource->is<mbgl::style::GeoJSONSource>()) { - source = [[MGLGeoJSONSource alloc] initWithIdentifier:identifier]; - } else if (mbglSource->is<mbgl::style::RasterSource>()) { - source = [[MGLRasterSource alloc] initWithIdentifier:identifier]; + if (auto vectorSource = source->as<mbgl::style::VectorSource>()) { + return [[MGLVectorSource alloc] initWithRawSource:vectorSource]; + } else if (auto geoJSONSource = source->as<mbgl::style::GeoJSONSource>()) { + return [[MGLGeoJSONSource alloc] initWithRawSource:geoJSONSource]; + } else if (auto rasterSource = source->as<mbgl::style::RasterSource>()) { + return [[MGLRasterSource alloc] initWithRawSource:rasterSource]; } else { - source = [[MGLSource alloc] initWithIdentifier:identifier]; + return [[MGLSource alloc] initWithRawSource:source]; } - - source.rawSource = mbglSource; - - return source; } - (void)addSource:(MGLSource *)source @@ -206,6 +202,25 @@ static NSURL *MGLStyleURL_emerald; [source removeFromMapView:self.mapView]; } +- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { + // It’d be incredibly convenient to use -sources here, but this operation + // depends on the sources being sorted in ascending order by creation, as + // with the std::vector used in mbgl. + auto rawSources = self.mapView.mbglMap->getSources(); + NSMutableArray *infos = [NSMutableArray arrayWithCapacity:rawSources.size()]; + for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) { + MGLSource *source = [self sourceFromMBGLSource:*rawSource]; + if (![source isKindOfClass:[MGLVectorSource class]] + && ![source isKindOfClass:[MGLRasterSource class]]) { + continue; + } + + NSArray *tileSetInfos = [[(id)source tileSet] attributionInfosWithFontSize:fontSize linkColor:linkColor]; + [infos growArrayByAddingAttributionInfosFromArray:tileSetInfos]; + } + return infos; +} + #pragma mark Style layers - (NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h index ee4a30c887..23ce8fbee0 100644 --- a/platform/darwin/src/MGLStyle_Private.h +++ b/platform/darwin/src/MGLStyle_Private.h @@ -2,11 +2,10 @@ #import "MGLStyleLayer.h" #import "MGLFillStyleLayer.h" -#import <mbgl/util/default_styles.hpp> -#include <mbgl/mbgl.hpp> NS_ASSUME_NONNULL_BEGIN +@class MGLAttributionInfo; @class MGLMapView; @class MGLOpenGLStyleLayer; @@ -16,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, readonly, weak) MGLMapView *mapView; +- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + @property (nonatomic, readonly, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers; - (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration; diff --git a/platform/darwin/src/MGLTileSet.h b/platform/darwin/src/MGLTileSet.h index 08a34338b1..88bc7e4ae0 100644 --- a/platform/darwin/src/MGLTileSet.h +++ b/platform/darwin/src/MGLTileSet.h @@ -17,6 +17,32 @@ typedef NS_ENUM(NSUInteger, MGLTileSetScheme) { */ @interface MGLTileSet : NSObject +#pragma mark Creating a Tile Set + +/** + Initializes and returns a new tile set object. + + @param tileURLTemplates An `NSArray` of `NSString` objects that represent the + tile templates. + @return The initialized tile set object. + */ +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates; + +/** + Initializes and returns a new tile set object. + + @param tileURLTemplates An `NSArray` of `NSString` objects that represent the + tile templates. + @param minimumZoomLevel An `NSUInteger`; specifies the minimum zoom level at + which to display tiles. + @param maximumZoomLevel An `NSUInteger`; specifies the maximum zoom level at + which to display tiles. + @return The initialized tile set object. + */ +- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel; + +#pragma mark Accessing Tile Set Metadata + /** An `NSArray` of `NSString` objects that represent the tile templates. */ @@ -51,28 +77,6 @@ typedef NS_ENUM(NSUInteger, MGLTileSetScheme) { */ @property (nonatomic) MGLTileSetScheme scheme; -/** - Initializes and returns a new tile set object. - - @param tileURLTemplates An `NSArray` of `NSString` objects that represent the - tile templates. - @return The initialized tile set object. - */ -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates; - -/** - Initializes and returns a new tile set object. - - @param tileURLTemplates An `NSArray` of `NSString` objects that represent the - tile templates. - @param minimumZoomLevel An `NSUInteger`; specifies the minimum zoom level at - which to display tiles. - @param maximumZoomLevel An `NSUInteger`; specifies the maximum zoom level at - which to display tiles. - @return The initialized tile set object. - */ -- (instancetype)initWithTileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates minimumZoomLevel:(NSUInteger)minimumZoomLevel maximumZoomLevel:(NSUInteger)maximumZoomLevel; - @end NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLTileSet.mm b/platform/darwin/src/MGLTileSet.mm index f795545eed..6afc6c19af 100644 --- a/platform/darwin/src/MGLTileSet.mm +++ b/platform/darwin/src/MGLTileSet.mm @@ -1,5 +1,7 @@ #import "MGLTileSet.h" +#import "MGLAttributionInfo.h" + #include <mbgl/util/tileset.hpp> @implementation MGLTileSet @@ -57,6 +59,12 @@ _maximumZoomLevel = maximumZoomLevel; } +- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor { + return [MGLAttributionInfo attributionInfosFromHTMLString:self.attribution + fontSize:fontSize + linkColor:linkColor]; +} + - (mbgl::Tileset)mbglTileset { mbgl::Tileset tileset; diff --git a/platform/darwin/src/MGLTileSet_Private.h b/platform/darwin/src/MGLTileSet_Private.h index 6a14d428db..038fe57fa2 100644 --- a/platform/darwin/src/MGLTileSet_Private.h +++ b/platform/darwin/src/MGLTileSet_Private.h @@ -2,8 +2,23 @@ #include <mbgl/util/tileset.hpp> +NS_ASSUME_NONNULL_BEGIN + +@class MGLAttributionInfo; + @interface MGLTileSet (Private) +/** + A structured representation of the `attribution` property. The default value is + `nil`. + + @param fontSize The default text size in points. + @param linkColor The default link color. + */ +- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor; + - (mbgl::Tileset)mbglTileset; -@end
\ No newline at end of file +@end + +NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm index ab68d45ba1..b5ec0b33be 100644 --- a/platform/darwin/src/MGLVectorSource.mm +++ b/platform/darwin/src/MGLVectorSource.mm @@ -1,4 +1,4 @@ -#import "MGLVectorSource.h" +#import "MGLVectorSource_Private.h" #import "MGLMapView_Private.h" #import "MGLSource_Private.h" @@ -9,6 +9,8 @@ @interface MGLVectorSource () +- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource NS_DESIGNATED_INITIALIZER; + @property (nonatomic) mbgl::style::VectorSource *rawSource; @end @@ -38,6 +40,16 @@ return self; } +- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource { + if (self = [super initWithRawSource:rawSource]) { + if (auto attribution = rawSource->getAttribution()) { + _tileSet = [[MGLTileSet alloc] initWithTileURLTemplates:@[]]; + _tileSet.attribution = @(attribution->c_str()); + } + } + return self; +} + - (void)commonInit { std::unique_ptr<mbgl::style::VectorSource> source; diff --git a/platform/darwin/src/MGLVectorSource_Private.h b/platform/darwin/src/MGLVectorSource_Private.h new file mode 100644 index 0000000000..ce6bccdbae --- /dev/null +++ b/platform/darwin/src/MGLVectorSource_Private.h @@ -0,0 +1,13 @@ +#import "MGLVectorSource.h" + +namespace mbgl { + namespace style { + class VectorSource; + } +} + +@interface MGLVectorSource (Private) + +- (instancetype)initWithRawSource:(mbgl::style::VectorSource *)rawSource; + +@end diff --git a/platform/darwin/src/NSString+MGLAdditions.h b/platform/darwin/src/NSString+MGLAdditions.h index 5b549affd5..45fea25588 100644 --- a/platform/darwin/src/NSString+MGLAdditions.h +++ b/platform/darwin/src/NSString+MGLAdditions.h @@ -4,9 +4,22 @@ NS_ASSUME_NONNULL_BEGIN @interface NSString (MGLAdditions) +/** Returns the range spanning the entire receiver. */ +- (NSRange)mgl_wholeRange; + /** Returns the receiver if non-empty or nil if empty. */ - (nullable NSString *)mgl_stringOrNilIfEmpty; @end +@interface NSAttributedString (MGLAdditions) + +/** Returns the range spanning the entire receiver. */ +- (NSRange)mgl_wholeRange; + +/** Returns a copy of the receiver with leading and trailing members of the given set removed. */ +- (NSAttributedString *)mgl_attributedStringByTrimmingCharactersInSet:(NSCharacterSet *)set; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/darwin/src/NSString+MGLAdditions.m b/platform/darwin/src/NSString+MGLAdditions.m index 969886651b..04a65dc5e2 100644 --- a/platform/darwin/src/NSString+MGLAdditions.m +++ b/platform/darwin/src/NSString+MGLAdditions.m @@ -2,9 +2,30 @@ @implementation NSString (MGLAdditions) -- (nullable NSString *)mgl_stringOrNilIfEmpty -{ +- (NSRange)mgl_wholeRange { + return NSMakeRange(0, self.length); +} + +- (nullable NSString *)mgl_stringOrNilIfEmpty { return self.length ? self : nil; } @end + +@implementation NSAttributedString (MGLAdditions) + +- (NSRange)mgl_wholeRange { + return NSMakeRange(0, self.length); +} + +- (NSAttributedString *)mgl_attributedStringByTrimmingCharactersInSet:(NSCharacterSet *)set { + NSScanner *scanner = [NSScanner scannerWithString:self.string]; + scanner.charactersToBeSkipped = nil; + NSString *prefix; + [scanner scanCharactersFromSet:set intoString:&prefix]; + + NSString *trimmedString = [self.string stringByTrimmingCharactersInSet:set]; + return [self attributedSubstringFromRange:NSMakeRange(prefix.length, trimmedString.length)]; +} + +@end |