From 1fac5322fbf88ddbcb510a78083a9e9db1eb6f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Minh=20Nguye=CC=82=CC=83n?= Date: Tue, 3 Jul 2018 03:19:30 -0700 Subject: [macos] Import GeoJSON Added an Import command to the File menu for adding the contents of a GeoJSON file to the map. simplestyle-spec formatting is applied to layers via a handful of expressions. Dropped pins include any details provided through simplestyle-spec properties. Cherry-picked from a93dca349d4768e0a6a763332e636e389e2b9f2d. --- platform/macos/app/Base.lproj/MainMenu.xib | 32 +++++++----- platform/macos/app/DroppedPinAnnotation.h | 5 ++ platform/macos/app/DroppedPinAnnotation.m | 9 +++- platform/macos/app/MapDocument.m | 80 +++++++++++++++++++++++++++++- 4 files changed, 111 insertions(+), 15 deletions(-) diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib index 8f0aeaf69c..6f8f24ce99 100644 --- a/platform/macos/app/Base.lproj/MainMenu.xib +++ b/platform/macos/app/Base.lproj/MainMenu.xib @@ -1,8 +1,8 @@ - + - + @@ -129,6 +129,14 @@ + + + + + + + + @@ -666,7 +674,7 @@ CA - + @@ -690,7 +698,7 @@ CA - + @@ -742,7 +750,7 @@ CA - + @@ -764,7 +772,7 @@ CA - + @@ -776,7 +784,7 @@ CA - + @@ -796,7 +804,7 @@ CA - + @@ -813,7 +821,7 @@ CA - + @@ -830,7 +838,7 @@ CA - + @@ -851,7 +859,7 @@ CA - + @@ -872,7 +880,7 @@ CA - + diff --git a/platform/macos/app/DroppedPinAnnotation.h b/platform/macos/app/DroppedPinAnnotation.h index 435a56738b..0897219b13 100644 --- a/platform/macos/app/DroppedPinAnnotation.h +++ b/platform/macos/app/DroppedPinAnnotation.h @@ -1,10 +1,15 @@ #import +NS_ASSUME_NONNULL_BEGIN + @interface DroppedPinAnnotation : MGLPointAnnotation +@property (nonatomic, copy, nullable) NSString *note; @property (nonatomic, readonly) NSTimeInterval elapsedShownTime; - (void)resume; - (void)pause; @end + +NS_ASSUME_NONNULL_END diff --git a/platform/macos/app/DroppedPinAnnotation.m b/platform/macos/app/DroppedPinAnnotation.m index d7bd4068dc..b601405095 100644 --- a/platform/macos/app/DroppedPinAnnotation.m +++ b/platform/macos/app/DroppedPinAnnotation.m @@ -61,8 +61,13 @@ static MGLCoordinateFormatter *DroppedPinCoordinateFormatter; - (void)update:(NSTimer *)timer { NSString *coordinate = [DroppedPinCoordinateFormatter stringFromCoordinate:self.coordinate]; - NSString *elapsedTime = [_timeIntervalTransformer transformedValue:@(self.elapsedShownTime)]; - self.subtitle = [NSString stringWithFormat:@"%@\nSelected for %@", coordinate, elapsedTime]; + if (self.note) { + self.subtitle = [@[self.note, coordinate] componentsJoinedByString:@"\n"]; + } else { + NSString *elapsedTime = [_timeIntervalTransformer transformedValue:@(self.elapsedShownTime)]; + NSString *elapsedString = [NSString stringWithFormat:@"Selected for %@", elapsedTime]; + self.subtitle = [@[coordinate, elapsedString] componentsJoinedByString:@"\n"]; + } } @end diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m index 4ee6050565..9ba28f3b37 100644 --- a/platform/macos/app/MapDocument.m +++ b/platform/macos/app/MapDocument.m @@ -177,6 +177,66 @@ NSArray> *MBXFlattenedShapes(NSArray> *sha #pragma mark File methods +- (IBAction)import:(id)sender { + NSOpenPanel *panel = [NSOpenPanel openPanel]; + panel.allowedFileTypes = @[@"public.json", @"json", @"geojson"]; + panel.allowsMultipleSelection = YES; + + __weak __typeof__(self) weakSelf = self; + [panel beginSheetModalForWindow:self.window completionHandler:^(NSModalResponse result) { + if (result != NSFileHandlingPanelOKButton) { + return; + } + + for (NSURL *url in panel.URLs) { + [weakSelf importFromURL:url]; + } + }]; +} + +/** + Adds the contents of the GeoJSON file at the given URL to the map. + + GeoJSON features are styled according to + [simplestyle-spec](https://github.com/mapbox/simplestyle-spec/tree/master/1.1.0/). + */ +- (void)importFromURL:(NSURL *)url { + MGLStyle *style = self.mapView.style; + if (!style) { + return; + } + + MGLShapeSource *source = [[MGLShapeSource alloc] initWithIdentifier:[NSUUID UUID].UUIDString URL:url options:nil]; + [self.mapView.style addSource:source]; + + NSString *pointIdentifier = [NSString stringWithFormat:@"%@ marker", source.identifier]; + MGLSymbolStyleLayer *pointLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:pointIdentifier source:source]; + pointLayer.iconImageName = + [NSExpression expressionWithFormat:@"mgl_join({%K, '-', CAST(TERNARY(%K = 'small', 11, 15), 'NSString')})", + @"marker-symbol", @"marker-size"]; + pointLayer.iconScale = [NSExpression expressionForConstantValue:@1]; + pointLayer.iconColor = [NSExpression expressionWithFormat:@"CAST(mgl_coalesce({%K, '#7e7e7e'}), 'NSColor')", + @"marker-color"]; + pointLayer.iconAllowsOverlap = [NSExpression expressionForConstantValue:@YES]; + [style addLayer:pointLayer]; + + NSString *fillIdentifier = [NSString stringWithFormat:@"%@ fill", source.identifier]; + MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:fillIdentifier source:source]; + fillLayer.predicate = [NSPredicate predicateWithFormat:@"fill != nil OR %K != nil", @"fill-opacity"]; + fillLayer.fillColor = [NSExpression expressionWithFormat:@"CAST(mgl_coalesce({fill, '#555555'}), 'NSColor')"]; + fillLayer.fillOpacity = [NSExpression expressionWithFormat:@"mgl_coalesce({%K, 0.5})", @"fill-opacity"]; + [style addLayer:fillLayer]; + + NSString *lineIdentifier = [NSString stringWithFormat:@"%@ stroke", source.identifier]; + MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:lineIdentifier source:source]; + lineLayer.lineColor = [NSExpression expressionWithFormat:@"CAST(mgl_coalesce({stroke, '#555555'}), 'NSColor')"]; + lineLayer.lineOpacity = [NSExpression expressionWithFormat:@"mgl_coalesce({%K, 1.0})", @"stroke-opacity"]; + lineLayer.lineWidth = [NSExpression expressionWithFormat:@"mgl_coalesce({%K, 2})", @"stroke-width"]; + lineLayer.lineCap = [NSExpression expressionForConstantValue:@"round"]; + lineLayer.lineJoin = [NSExpression expressionForConstantValue:@"bevel"]; + [style addLayer:lineLayer]; +} + - (IBAction)takeSnapshot:(id)sender { MGLMapCamera *camera = self.mapView.camera; @@ -966,15 +1026,30 @@ NSArray> *MBXFlattenedShapes(NSArray> *sha - (DroppedPinAnnotation *)pinAtPoint:(NSPoint)point { NSArray *features = [self.mapView visibleFeaturesAtPoint:point]; NSString *title; + NSString *description; for (id feature in features) { if (!title) { - title = [feature attributeForKey:@"name_en"] ?: [feature attributeForKey:@"name"]; + title = [feature attributeForKey:@"title"] ?: [feature attributeForKey:@"name_en"] ?: [feature attributeForKey:@"name"]; + + // simplestyle-spec defines a “description” attribute in HTML format. + NSString *featureDescription = [feature attributeForKey:@"description"]; + if (featureDescription) { + // Convert HTML to plain text, because the default popover is + // bound to an NSString-typed property. + NSData *data = [featureDescription dataUsingEncoding:NSUTF8StringEncoding]; + description = [[NSAttributedString alloc] initWithHTML:data options:@{} documentAttributes:nil].string; + } + + if (title) { + break; + } } } DroppedPinAnnotation *annotation = [[DroppedPinAnnotation alloc] init]; annotation.coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView]; annotation.title = title ?: @"Dropped Pin"; + annotation.note = description; _spellOutNumberFormatter.numberStyle = NSNumberFormatterSpellOutStyle; if (_showsToolTipsOnDroppedPins) { NSString *formattedNumber = [_spellOutNumberFormatter stringFromNumber:@(++_droppedPinCounter)]; @@ -1184,6 +1259,9 @@ NSArray> *MBXFlattenedShapes(NSArray> *sha if (menuItem.action == @selector(giveFeedback:)) { return YES; } + if (menuItem.action == @selector(import:)) { + return YES; + } if (menuItem.action == @selector(takeSnapshot:)) { return !(_snapshotter && [_snapshotter isLoading]); } -- cgit v1.2.1