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

Commit 27db3bb

Browse files
committed
[ios, macos] Use MGLAttributionInfo for source attribution
Made MGLAttributionInfo public. Replaced MGLTileSource’s attribution property with an attributionInfos property set to an array of MGLAttributionInfo objects. Added an MGLTileSourceOption for specifying an array of MGLAttributionInfo objects instead of an HTML string (either is acceptable when creating an MGLTileSource).
1 parent 6ffb8b5 commit 27db3bb

19 files changed

+244
-57
lines changed

platform/darwin/src/MGLAttributionInfo.h

+29-25
Original file line numberDiff line numberDiff line change
@@ -13,45 +13,49 @@ NS_ASSUME_NONNULL_BEGIN
1313
@interface MGLAttributionInfo : NSObject
1414

1515
/**
16-
Parses and returns the attribution infos contained in the given HTML source
17-
code string.
16+
Returns an initialized attribution info object with the given title and URL.
1817
19-
@param htmlString The HTML source code to parse.
20-
@param fontSize The default text size in points.
21-
@param linkColor The default link color.
18+
@param title The attribution statement’s title.
19+
@param URL A URL to more information about the entity named in the attribution.
20+
@return An initialized attribution info object.
2221
*/
23-
+ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(nullable NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
24-
2522
- (instancetype)initWithTitle:(NSAttributedString *)title URL:(nullable NSURL *)URL;
2623

24+
/**
25+
The attribution statement’s attributed title text.
26+
*/
2727
@property (nonatomic) NSAttributedString *title;
28-
@property (nonatomic, nullable) NSURL *URL;
29-
@property (nonatomic, getter=isFeedbackLink) BOOL feedbackLink;
30-
31-
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel;
3228

33-
@end
34-
35-
@interface NSMutableArray (MGLAttributionInfoAdditions)
29+
/**
30+
The URL to more information about the entity named in the attribution.
31+
32+
If this property is set, the attribution statement should be displayed as a
33+
hyperlink or action button. Otherwise, if it is `nil`, the attribution
34+
statement should be displayed as plain text.
35+
*/
36+
@property (nonatomic, nullable) NSURL *URL;
3637

3738
/**
38-
Adds the given attribution info object to the receiver as long as it isn’t
39-
redundant to any object already in the receiver. Any existing object that is
40-
redundant to the given object is replaced by the given object.
39+
A Boolean value indicating whether the attribution statement is a shortcut to a
40+
feedback tool.
4141
42-
@param info The info object to add to the receiver.
43-
@return True if the given info object was added to the receiver.
42+
If this property is set, the statement should be treated as a way for the user
43+
to provide feedback rather than an attribution statement.
4444
*/
45-
- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info;
45+
@property (nonatomic, getter=isFeedbackLink) BOOL feedbackLink;
4646

4747
/**
48-
Adds each of the given attribution info objects to the receiver as long as it
49-
isn’t redundant to any object already in the receiver. Any existing object that
50-
is redundant to the given object is replaced by the given object.
48+
Returns a copy of the `URL` property modified to account for the given center
49+
coordinate and zoom level.
5150
52-
@param infos An array of info objects to add to the receiver.
51+
@param centerCoordinate The map’s center coordinate.
52+
@param zoomLevel The map’s zoom level. See `MGLMapView`’s `zoomLevel` property
53+
for more information.
54+
@return A modified URL containing a fragment that points to the specified
55+
viewport. If the `feedbackLink` property is set to `NO`, this method returns
56+
`nil`.
5357
*/
54-
- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos;
58+
- (nullable NSURL *)feedbackURLAtCenterCoordinate:(CLLocationCoordinate2D)centerCoordinate zoomLevel:(double)zoomLevel;
5559

5660
@end
5761

platform/darwin/src/MGLAttributionInfo.mm

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#import "MGLAttributionInfo.h"
1+
#import "MGLAttributionInfo_Private.h"
22

33
#if TARGET_OS_IPHONE
44
#import <UIKit/UIKit.h>
@@ -7,6 +7,7 @@
77
#endif
88

99
#import "MGLMapCamera.h"
10+
#import "NSArray+MGLAdditions.h"
1011
#import "NSString+MGLAdditions.h"
1112

1213
#include <string>
@@ -88,6 +89,18 @@ @implementation MGLAttributionInfo
8889
return infos;
8990
}
9091

92+
+ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos {
93+
NSMutableArray *titles = [NSMutableArray arrayWithCapacity:attributionInfos.count];
94+
for (MGLAttributionInfo *info in attributionInfos) {
95+
NSMutableAttributedString *title = info.title.mutableCopy;
96+
if (info.URL) {
97+
[title addAttribute:NSLinkAttributeName value:info.URL range:title.mgl_wholeRange];
98+
}
99+
[titles addObject:title];
100+
}
101+
return [titles mgl_attributedComponentsJoinedByString:@" "];
102+
}
103+
91104
- (instancetype)initWithTitle:(NSAttributedString *)title URL:(NSURL *)URL {
92105
if (self = [super init]) {
93106
_title = title;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
#import <Foundation/Foundation.h>
2+
#import <CoreGraphics/CoreGraphics.h>
3+
#import <CoreLocation/CoreLocation.h>
4+
5+
#import "MGLAttributionInfo.h"
6+
7+
NS_ASSUME_NONNULL_BEGIN
8+
9+
@interface MGLAttributionInfo (Private)
10+
11+
/**
12+
Parses and returns the attribution infos contained in the given HTML source
13+
code string.
14+
15+
@param htmlString The HTML source code to parse.
16+
@param fontSize The default text size in points.
17+
@param linkColor The default link color.
18+
*/
19+
+ (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosFromHTMLString:(nullable NSString *)htmlString fontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
20+
21+
+ (NSAttributedString *)attributedStringForAttributionInfos:(NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos;
22+
23+
@end
24+
25+
@interface NSMutableArray (MGLAttributionInfoAdditions)
26+
27+
/**
28+
Adds the given attribution info object to the receiver as long as it isn’t
29+
redundant to any object already in the receiver. Any existing object that is
30+
redundant to the given object is replaced by the given object.
31+
32+
@param info The info object to add to the receiver.
33+
@return True if the given info object was added to the receiver.
34+
*/
35+
- (void)growArrayByAddingAttributionInfo:(MGLAttributionInfo *)info;
36+
37+
/**
38+
Adds each of the given attribution info objects to the receiver as long as it
39+
isn’t redundant to any object already in the receiver. Any existing object that
40+
is redundant to the given object is replaced by the given object.
41+
42+
@param infos An array of info objects to add to the receiver.
43+
*/
44+
- (void)growArrayByAddingAttributionInfosFromArray:(NS_ARRAY_OF(MGLAttributionInfo *) *)infos;
45+
46+
@end
47+
48+
NS_ASSUME_NONNULL_END

platform/darwin/src/MGLRasterSource.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ - (void)setRawSource:(mbgl::style::RasterSource *)rawSource {
8585
super.rawSource = rawSource;
8686
}
8787

88-
- (NSString *)attribution {
88+
- (NSString *)attributionHTMLString {
8989
auto attribution = self.rawSource->getAttribution();
9090
return attribution ? @(attribution->c_str()) : nil;
9191
}

platform/darwin/src/MGLStyle.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#import "MGLRasterSource.h"
2323
#import "MGLShapeSource.h"
2424

25-
#import "MGLAttributionInfo.h"
25+
#import "MGLAttributionInfo_Private.h"
2626

2727
#include <mbgl/util/default_styles.hpp>
2828
#include <mbgl/sprite/sprite_image.hpp>

platform/darwin/src/MGLTileSource.h

+39-13
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
NS_ASSUME_NONNULL_BEGIN
77

8+
@class MGLAttributionInfo;
9+
810
/**
911
Options for `MGLTileSource` objects.
1012
*/
@@ -32,20 +34,43 @@ extern const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel;
3234

3335
#if TARGET_OS_IPHONE
3436
/**
35-
A string to be displayed in an action sheet when the source is part of a map
36-
view’s style and the map view’s attribution button is pressed.
37+
An HTML string defining the buttons to be displayed in an action sheet when the
38+
source is part of a map view’s style and the map view’s attribution button is
39+
pressed.
40+
41+
By default, no attribution statements are displayed. If the
42+
`MGLTileSourceOptionAttributionInfos` option is specified, this option is
43+
ignored.
44+
*/
45+
extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
46+
47+
/**
48+
An array of `MGLAttributionInfo` objects defining the buttons to be displayed
49+
in an action sheet when the source is part of a map view’s style and the map
50+
view’s attribution button is pressed.
3751
38-
The default value for this option is `nil`.
52+
By default, no attribution statements are displayed.
3953
*/
40-
extern const MGLTileSourceOption MGLTileSourceOptionAttribution;
54+
extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
4155
#else
4256
/**
43-
A string to be displayed in the map view’s attribution view when the source is
44-
part of the map view’s style.
57+
An HTML string defining the buttons to be displayed in the map view’s
58+
attribution view when the source is part of the map view’s style.
59+
60+
By default, no attribution statements are displayed. If the
61+
`MGLTileSourceOptionAttributionInfos` option is specified, this option is
62+
ignored.
63+
*/
64+
extern const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString;
65+
66+
/**
67+
An array of `MGLAttributionInfo` objects defining the buttons to be displayed
68+
in the map view’s attribution view when the source is part of the map view’s
69+
style.
4570
46-
The default value for this option is `nil`.
71+
By default, no attribution statements are displayed.
4772
*/
48-
extern const MGLTileSourceOption MGLTileSourceOptionAttribution;
73+
extern const MGLTileSourceOption MGLTileSourceOptionAttributionInfos;
4974
#endif
5075

5176
/**
@@ -140,13 +165,14 @@ typedef NS_ENUM(NSUInteger, MGLTileCoordinateSystem) {
140165
#pragma mark Accessing Attribution Strings
141166

142167
/**
143-
An `NSString` object that contains an attribution to be displayed when the map
144-
is shown to a user.
168+
An array of `MGLAttributionInfo` objects that define the attribution
169+
statements to be displayed when the map is shown to the user.
145170
146-
The default value is `nil`. If the source is initialized with a configuration
147-
URL, this property is also `nil` until the configuration JSON file is loaded.
171+
By default, this array is empty. If the source is initialized with a
172+
configuration URL, this array is also empty until the configuration JSON file
173+
is loaded.
148174
*/
149-
@property (nonatomic, copy, nullable, readonly) NSString *attribution;
175+
@property (nonatomic, copy, readonly) NS_ARRAY_OF(MGLAttributionInfo *) *attributionInfos;
150176

151177
@end
152178

platform/darwin/src/MGLTileSource.mm

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
#import "MGLTileSource_Private.h"
22

3-
#import "MGLAttributionInfo.h"
3+
#import "MGLAttributionInfo_Private.h"
4+
#import "NSString+MGLAdditions.h"
5+
6+
#if TARGET_OS_IPHONE
7+
#import <UIKit/UIKit.h>
8+
#else
9+
#import <Cocoa/Cocoa.h>
10+
#endif
411

512
#include <mbgl/util/tileset.hpp>
613

714
const MGLTileSourceOption MGLTileSourceOptionMinimumZoomLevel = @"MGLTileSourceOptionMinimumZoomLevel";
815
const MGLTileSourceOption MGLTileSourceOptionMaximumZoomLevel = @"MGLTileSourceOptionMaximumZoomLevel";
9-
const MGLTileSourceOption MGLTileSourceOptionAttribution = @"MGLTileSourceOptionAttribution";
16+
const MGLTileSourceOption MGLTileSourceOptionAttributionHTMLString = @"MGLTileSourceOptionAttributionHTMLString";
17+
const MGLTileSourceOption MGLTileSourceOptionAttributionInfos = @"MGLTileSourceOptionAttributionInfos";
1018
const MGLTileSourceOption MGLTileSourceOptionTileCoordinateSystem = @"MGLTileSourceOptionTileCoordinateSystem";
1119

1220
@implementation MGLTileSource
@@ -19,13 +27,17 @@ - (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_A
1927
return [super initWithIdentifier:identifier];
2028
}
2129

22-
- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor {
23-
return [MGLAttributionInfo attributionInfosFromHTMLString:self.attribution
30+
- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfos {
31+
return [self attributionInfosWithFontSize:0 linkColor:nil];
32+
}
33+
34+
- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor {
35+
return [MGLAttributionInfo attributionInfosFromHTMLString:self.attributionHTMLString
2436
fontSize:fontSize
2537
linkColor:linkColor];
2638
}
2739

28-
- (NSString *)attribution {
40+
- (NSString *)attributionHTMLString {
2941
[NSException raise:@"MGLAbstractClassException"
3042
format:@"MGLTileSource is an abstract class"];
3143
return nil;
@@ -61,14 +73,35 @@ - (NSString *)attribution {
6173
format:@"MGLTileSourceOptionMinimumZoomLevel must be less than MGLTileSourceOptionMaximumZoomLevel."];
6274
}
6375

64-
if (NSString *attribution = options[MGLTileSourceOptionAttribution]) {
76+
if (NSString *attribution = options[MGLTileSourceOptionAttributionHTMLString]) {
6577
if (![attribution isKindOfClass:[NSString class]]) {
6678
[NSException raise:NSInvalidArgumentException
67-
format:@"MGLTileSourceOptionAttribution must be set to a string."];
79+
format:@"MGLTileSourceOptionAttributionHTMLString must be set to a string."];
6880
}
6981
tileSet.attribution = attribution.UTF8String;
7082
}
7183

84+
if (NSArray *attributionInfos = options[MGLTileSourceOptionAttributionInfos]) {
85+
if (![attributionInfos isKindOfClass:[NSArray class]]) {
86+
[NSException raise:NSInvalidArgumentException
87+
format:@"MGLTileSourceOptionAttributionInfos must be set to a string."];
88+
}
89+
90+
NSAttributedString *attributedString = [MGLAttributionInfo attributedStringForAttributionInfos:attributionInfos];
91+
#if TARGET_OS_IPHONE
92+
static NSString * const NSExcludedElementsDocumentAttribute = @"ExcludedElements";
93+
#endif
94+
NSDictionary *documentAttributes = @{
95+
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
96+
NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding),
97+
// The attribution string is meant to be a simple, inline fragment, not a full-fledged, validating document.
98+
NSExcludedElementsDocumentAttribute: @[@"XML", @"DOCTYPE", @"html", @"head", @"meta", @"title", @"style", @"body", @"p"],
99+
};
100+
NSData *data = [attributedString dataFromRange:attributedString.mgl_wholeRange documentAttributes:documentAttributes error:NULL];
101+
NSString *html = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
102+
tileSet.attribution = html.UTF8String;
103+
}
104+
72105
if (NSNumber *tileCoordinateSystemNumber = options[MGLTileSourceOptionTileCoordinateSystem]) {
73106
if (![tileCoordinateSystemNumber isKindOfClass:[NSValue class]]) {
74107
[NSException raise:NSInvalidArgumentException

platform/darwin/src/MGLTileSource_Private.h

+11-3
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,22 @@ namespace mbgl {
1212

1313
@interface MGLTileSource (Private)
1414

15+
/**
16+
An HTML string to be displayed as attribution when the map is shown to a user.
17+
18+
The default value is `nil`. If the source is initialized with a configuration
19+
URL, this property is also `nil` until the configuration JSON file is loaded.
20+
*/
21+
@property (nonatomic, copy, nullable, readonly) NSString *attributionHTMLString;
22+
1523
/**
1624
A structured representation of the `attribution` property. The default value is
1725
`nil`.
1826
19-
@param fontSize The default text size in points.
20-
@param linkColor The default link color.
27+
@param fontSize The default text size in points, or 0 to use the default.
28+
@param linkColor The default link color, or `nil` to use the default.
2129
*/
22-
- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
30+
- (NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
2331

2432
@end
2533

platform/darwin/src/MGLVectorSource.mm

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ - (void)setRawSource:(mbgl::style::VectorSource *)rawSource {
6969
super.rawSource = rawSource;
7070
}
7171

72-
- (NSString *)attribution {
72+
- (NSString *)attributionHTMLString {
7373
auto attribution = self.rawSource->getAttribution();
7474
return attribution ? @(attribution->c_str()) : nil;
7575
}

platform/darwin/src/NSArray+MGLAdditions.h

+3
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,7 @@
66

77
- (std::vector<mbgl::Value>)mgl_vector;
88

9+
/** Returns a string resulting from inserting a separator between each attributed string in the array */
10+
- (NSAttributedString *)mgl_attributedComponentsJoinedByString:(NSString *)separator;
11+
912
@end

0 commit comments

Comments
 (0)