Merge remote-tracking branch 'origin/master' into 1128-convert-booleans
This commit is contained in:
@@ -1,16 +1,24 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
extern NSString *const MGLEventMapLoad;
|
||||
extern NSString *const MGLEventMapTap;
|
||||
extern NSString *const MGLEventMapSingleTap;
|
||||
extern NSString *const MGLEventMapDoubleTap;
|
||||
extern NSString *const MGLEventMapTwoFingerSingleTap;
|
||||
extern NSString *const MGLEventMapQuickZoom;
|
||||
extern NSString *const MGLEventMapPanStart;
|
||||
extern NSString *const MGLEventMapPanEnd;
|
||||
extern NSString *const MGLEventMapPinchStart;
|
||||
extern NSString *const MGLEventMapRotateStart;
|
||||
extern NSString *const MGLEventMapLocation;
|
||||
extern NSString *const MGLEventTypeMapLoad;
|
||||
extern NSString *const MGLEventTypeMapTap;
|
||||
extern NSString *const MGLEventTypeMapDragEnd;
|
||||
extern NSString *const MGLEventTypeLocation;
|
||||
|
||||
extern NSString *const MGLEventKeyLatitude;
|
||||
extern NSString *const MGLEventKeyLongitude;
|
||||
extern NSString *const MGLEventKeyZoomLevel;
|
||||
extern NSString *const MGLEventKeyPushEnabled;
|
||||
extern NSString *const MGLEventKeyEmailEnabled;
|
||||
extern NSString *const MGLEventKeyGestureID;
|
||||
|
||||
extern NSString *const MGLEventGestureSingleTap;
|
||||
extern NSString *const MGLEventGestureDoubleTap;
|
||||
extern NSString *const MGLEventGestureTwoFingerSingleTap;
|
||||
extern NSString *const MGLEventGestureQuickZoom;
|
||||
extern NSString *const MGLEventGesturePanStart;
|
||||
extern NSString *const MGLEventGesturePinchStart;
|
||||
extern NSString *const MGLEventGestureRotateStart;
|
||||
|
||||
@interface MGLMapboxEvents : NSObject
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <iosfwd>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <mutex>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
@@ -159,8 +160,8 @@ public:
|
||||
const std::vector<std::string>& symbols);
|
||||
void removeAnnotation(uint32_t);
|
||||
void removeAnnotations(const std::vector<uint32_t>&);
|
||||
std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&) const;
|
||||
LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&) const;
|
||||
std::vector<uint32_t> getAnnotationsInBounds(const LatLngBounds&);
|
||||
LatLngBounds getBoundsForAnnotations(const std::vector<uint32_t>&);
|
||||
|
||||
// Debug
|
||||
void setDebug(bool value);
|
||||
@@ -200,6 +201,12 @@ private:
|
||||
// the stylesheet.
|
||||
void prepare();
|
||||
|
||||
// Runs the function in the map thread.
|
||||
void invokeTask(std::function<void()>&&);
|
||||
template <typename Fn> auto invokeSyncTask(const Fn& fn) -> decltype(fn());
|
||||
|
||||
void processTasks();
|
||||
|
||||
void updateAnnotationTiles(const std::vector<Tile::ID>&);
|
||||
|
||||
enum class Mode : uint8_t {
|
||||
@@ -219,6 +226,7 @@ private:
|
||||
std::thread thread;
|
||||
std::unique_ptr<uv::async> asyncTerminate;
|
||||
std::unique_ptr<uv::async> asyncUpdate;
|
||||
std::unique_ptr<uv::async> asyncInvoke;
|
||||
std::unique_ptr<uv::async> asyncRender;
|
||||
|
||||
bool terminating = false;
|
||||
@@ -257,6 +265,9 @@ private:
|
||||
std::set<util::ptr<StyleSource>> activeSources;
|
||||
|
||||
std::atomic<UpdateType> updated;
|
||||
|
||||
std::mutex mutexTask;
|
||||
std::queue<std::function<void()>> tasks;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -355,12 +355,12 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
const mbgl::LatLng latLng = mbglMap->getLatLng();
|
||||
const double zoom = mbglMap->getZoom();
|
||||
|
||||
[MGLMapboxEvents pushEvent:MGLEventMapLoad withAttributes:@{
|
||||
@"lat": @(latLng.latitude),
|
||||
@"lng": @(latLng.longitude),
|
||||
@"zoom": @(zoom),
|
||||
@"enabled.push": @([MGLMapboxEvents checkPushEnabled]),
|
||||
@"enabled.email": @([MGLMapboxEvents checkEmailEnabled])
|
||||
[MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{
|
||||
MGLEventKeyLatitude: @(latLng.latitude),
|
||||
MGLEventKeyLongitude: @(latLng.longitude),
|
||||
MGLEventKeyZoomLevel: @(zoom),
|
||||
MGLEventKeyPushEnabled: @([MGLMapboxEvents checkPushEnabled]),
|
||||
MGLEventKeyEmailEnabled: @([MGLMapboxEvents checkEmailEnabled])
|
||||
}];
|
||||
|
||||
return YES;
|
||||
@@ -586,7 +586,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handlePanGesture:(UIPanGestureRecognizer *)pan
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapPanStart forRecognizer:pan];
|
||||
[self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
|
||||
|
||||
if ( ! self.isScrollEnabled) return;
|
||||
|
||||
@@ -653,17 +653,17 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
CLLocationCoordinate2D panCoordinate = [self convertPoint:pointInView toCoordinateFromView:pan.view];
|
||||
double zoom = [self zoomLevel];
|
||||
|
||||
[MGLMapboxEvents pushEvent:MGLEventMapPanEnd withAttributes:@{
|
||||
@"lat": @(panCoordinate.latitude),
|
||||
@"lng": @(panCoordinate.longitude),
|
||||
@"zoom": @(zoom)
|
||||
[MGLMapboxEvents pushEvent:MGLEventTypeMapDragEnd withAttributes:@{
|
||||
MGLEventKeyLatitude: @(panCoordinate.latitude),
|
||||
MGLEventKeyLongitude: @(panCoordinate.longitude),
|
||||
MGLEventKeyZoomLevel: @(zoom)
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handlePinchGesture:(UIPinchGestureRecognizer *)pinch
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapPinchStart forRecognizer:pinch];
|
||||
[self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
|
||||
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
@@ -701,7 +701,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handleRotateGesture:(UIRotationGestureRecognizer *)rotate
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapRotateStart forRecognizer:rotate];
|
||||
[self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
|
||||
|
||||
if ( ! self.isRotateEnabled) return;
|
||||
|
||||
@@ -743,7 +743,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapSingleTap forRecognizer:singleTap];
|
||||
[self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap];
|
||||
|
||||
CGPoint tapPoint = [singleTap locationInView:self];
|
||||
|
||||
@@ -866,7 +866,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapDoubleTap forRecognizer:doubleTap];
|
||||
[self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
|
||||
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
@@ -897,7 +897,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handleTwoFingerTapGesture:(UITapGestureRecognizer *)twoFingerTap
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapTwoFingerSingleTap forRecognizer:twoFingerTap];
|
||||
[self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
|
||||
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
@@ -930,7 +930,7 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
|
||||
- (void)handleQuickZoomGesture:(UILongPressGestureRecognizer *)quickZoom
|
||||
{
|
||||
[self trackGestureEvent:MGLEventMapQuickZoom forRecognizer:quickZoom];
|
||||
[self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
|
||||
|
||||
if ( ! self.isZoomEnabled) return;
|
||||
|
||||
@@ -984,11 +984,11 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr;
|
||||
CLLocationCoordinate2D gestureCoordinate = [self convertPoint:pointInView toCoordinateFromView:recognizer.view];
|
||||
double zoom = [self zoomLevel];
|
||||
|
||||
[MGLMapboxEvents pushEvent:MGLEventMapTap withAttributes:@{
|
||||
@"lat": @(gestureCoordinate.latitude),
|
||||
@"lng": @(gestureCoordinate.longitude),
|
||||
@"zoom": @(zoom),
|
||||
@"gesture": gestureID
|
||||
[MGLMapboxEvents pushEvent:MGLEventTypeMapTap withAttributes:@{
|
||||
MGLEventKeyLatitude: @(gestureCoordinate.latitude),
|
||||
MGLEventKeyLongitude: @(gestureCoordinate.longitude),
|
||||
MGLEventKeyZoomLevel: @(zoom),
|
||||
MGLEventKeyGestureID: gestureID
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,17 +12,25 @@
|
||||
static NSString *const MGLMapboxEventsUserAgent = @"MapboxEventsiOS/1.0";
|
||||
static NSString *const MGLMapboxEventsAPIBase = @"https://api.tiles.mapbox.com";
|
||||
|
||||
NSString *const MGLEventMapLoad = @"map.load";
|
||||
NSString *const MGLEventMapTap = @"map.click";
|
||||
NSString *const MGLEventMapSingleTap = @"SingleTap";
|
||||
NSString *const MGLEventMapDoubleTap = @"DoubleTap";
|
||||
NSString *const MGLEventMapTwoFingerSingleTap = @"TwoFingerTap";
|
||||
NSString *const MGLEventMapQuickZoom = @"QuickZoom";
|
||||
NSString *const MGLEventMapPanStart = @"Pan";
|
||||
NSString *const MGLEventMapPanEnd = @"map.dragend";
|
||||
NSString *const MGLEventMapPinchStart = @"Pinch";
|
||||
NSString *const MGLEventMapRotateStart = @"Rotation";
|
||||
NSString *const MGLEventMapLocation = @"Location";
|
||||
NSString *const MGLEventTypeMapLoad = @"map.load";
|
||||
NSString *const MGLEventTypeMapTap = @"map.click";
|
||||
NSString *const MGLEventTypeMapDragEnd = @"map.dragend";
|
||||
NSString *const MGLEventTypeLocation = @"Location";
|
||||
|
||||
NSString *const MGLEventKeyLatitude = @"lat";
|
||||
NSString *const MGLEventKeyLongitude = @"lng";
|
||||
NSString *const MGLEventKeyZoomLevel = @"zoom";
|
||||
NSString *const MGLEventKeyPushEnabled = @"enabled.push";
|
||||
NSString *const MGLEventKeyEmailEnabled = @"enabled.email";
|
||||
NSString *const MGLEventKeyGestureID = @"gesture";
|
||||
|
||||
NSString *const MGLEventGestureSingleTap = @"SingleTap";
|
||||
NSString *const MGLEventGestureDoubleTap = @"DoubleTap";
|
||||
NSString *const MGLEventGestureTwoFingerSingleTap = @"TwoFingerTap";
|
||||
NSString *const MGLEventGestureQuickZoom = @"QuickZoom";
|
||||
NSString *const MGLEventGesturePanStart = @"Pan";
|
||||
NSString *const MGLEventGesturePinchStart = @"Pinch";
|
||||
NSString *const MGLEventGestureRotateStart = @"Rotation";
|
||||
|
||||
//
|
||||
// Threadsafety conventions:
|
||||
@@ -216,7 +224,7 @@ NSString *const MGLEventMapLocation = @"Location";
|
||||
// use of +pushEvent:withAttributes:.
|
||||
//
|
||||
- (void) pushEvent:(NSString *)event withAttributes:(NSDictionary *)attributeDictionary {
|
||||
// convert any BOOL types to string values written out like JS
|
||||
// conve+rt any BOOL types to string values written out like JS
|
||||
NSMutableDictionary *newAttributeDictionary = [NSMutableDictionary dictionaryWithCapacity:[attributeDictionary count]];
|
||||
NSString *key;
|
||||
NSObject *value;
|
||||
@@ -249,7 +257,7 @@ NSString *const MGLEventMapLocation = @"Location";
|
||||
|
||||
if (!event) return;
|
||||
|
||||
NSMutableDictionary *evt = [[NSMutableDictionary alloc] init];
|
||||
NSMutableDictionary *evt = [[NSMutableDictionary alloc] initWithDictionary:attributeDictionary];
|
||||
// mapbox-events stock attributes
|
||||
[evt setObject:event forKey:@"event"];
|
||||
[evt setObject:@(1) forKey:@"version"];
|
||||
@@ -268,11 +276,7 @@ NSString *const MGLEventMapLocation = @"Location";
|
||||
[evt setValue:[weakSelf getCurrentCellularNetworkConnectionType] forKey:@"cellularNetworkType"];
|
||||
[evt setValue:[weakSelf getWifiNetworkName] forKey:@"wifi"];
|
||||
[evt setValue:@([weakSelf getContentSizeScale]) forKey:@"accessibilityFontScale"];
|
||||
|
||||
for (NSString *key in [attributeDictionary allKeys]) {
|
||||
[evt setObject:[attributeDictionary valueForKey:key] forKey:key];
|
||||
}
|
||||
|
||||
|
||||
// Make Immutable Version
|
||||
NSDictionary *finalEvent = [NSDictionary dictionaryWithDictionary:evt];
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@
|
||||
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
|
||||
// Iterate through locations to pass all data
|
||||
for (CLLocation *loc in locations) {
|
||||
[MGLMapboxEvents pushEvent:MGLEventMapLocation withAttributes:@{
|
||||
@"lat": @(loc.coordinate.latitude),
|
||||
@"lng": @(loc.coordinate.longitude)
|
||||
[MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{
|
||||
MGLEventKeyLatitude: @(loc.coordinate.latitude),
|
||||
MGLEventKeyLongitude: @(loc.coordinate.longitude)
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,6 +144,11 @@ void Map::start(bool startPaused) {
|
||||
update();
|
||||
});
|
||||
|
||||
asyncInvoke = util::make_unique<uv::async>(env->loop, [this] {
|
||||
processTasks();
|
||||
});
|
||||
|
||||
|
||||
asyncRender = util::make_unique<uv::async>(env->loop, [this] {
|
||||
// Must be called in Map thread.
|
||||
assert(Environment::currentlyOn(ThreadType::Map));
|
||||
@@ -315,6 +320,42 @@ void Map::triggerRender() {
|
||||
asyncRender->send();
|
||||
}
|
||||
|
||||
// Runs the function in the map thread.
|
||||
void Map::invokeTask(std::function<void()>&& fn) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutexTask);
|
||||
tasks.emplace(::std::forward<std::function<void()>>(fn));
|
||||
}
|
||||
|
||||
// TODO: Once we have aligned static and continuous rendering, this should always dispatch
|
||||
// to the async queue.
|
||||
if (asyncInvoke) {
|
||||
asyncInvoke->send();
|
||||
} else {
|
||||
processTasks();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Fn> auto Map::invokeSyncTask(const Fn& fn) -> decltype(fn()) {
|
||||
std::promise<decltype(fn())> promise;
|
||||
invokeTask([&fn, &promise] { promise.set_value(fn()); });
|
||||
return promise.get_future().get();
|
||||
}
|
||||
|
||||
// Processes the functions that should be run in the map thread.
|
||||
void Map::processTasks() {
|
||||
std::queue<std::function<void()>> queue;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutexTask);
|
||||
queue.swap(tasks);
|
||||
}
|
||||
|
||||
while (!queue.empty()) {
|
||||
queue.front()();
|
||||
queue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::checkForPause() {
|
||||
std::unique_lock<std::mutex> lockRun (mutexRun);
|
||||
while (pausing) {
|
||||
@@ -542,27 +583,31 @@ std::string Map::getAccessToken() const {
|
||||
|
||||
void Map::setDefaultPointAnnotationSymbol(const std::string& symbol) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
annotationManager->setDefaultPointAnnotationSymbol(symbol);
|
||||
invokeTask([=] {
|
||||
annotationManager->setDefaultPointAnnotationSymbol(symbol);
|
||||
});
|
||||
}
|
||||
|
||||
double Map::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
|
||||
SpritePosition pos = sprite->getSpritePosition(symbol);
|
||||
|
||||
return -pos.height / pos.pixelRatio / 2;
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
return invokeSyncTask([&] {
|
||||
assert(sprite);
|
||||
const SpritePosition pos = sprite->getSpritePosition(symbol);
|
||||
return -pos.height / pos.pixelRatio / 2;
|
||||
});
|
||||
}
|
||||
|
||||
uint32_t Map::addPointAnnotation(const LatLng& point, const std::string& symbol) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
std::vector<LatLng> points({ point });
|
||||
std::vector<std::string> symbols({ symbol });
|
||||
return addPointAnnotations(points, symbols)[0];
|
||||
return addPointAnnotations({ point }, { symbol }).front();
|
||||
}
|
||||
|
||||
std::vector<uint32_t> Map::addPointAnnotations(const std::vector<LatLng>& points, const std::vector<std::string>& symbols) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
auto result = annotationManager->addPointAnnotations(points, symbols, *this);
|
||||
updateAnnotationTiles(result.first);
|
||||
return result.second;
|
||||
return invokeSyncTask([&] {
|
||||
auto result = annotationManager->addPointAnnotations(points, symbols, *this);
|
||||
updateAnnotationTiles(result.first);
|
||||
return result.second;
|
||||
});
|
||||
}
|
||||
|
||||
void Map::removeAnnotation(uint32_t annotation) {
|
||||
@@ -572,22 +617,28 @@ void Map::removeAnnotation(uint32_t annotation) {
|
||||
|
||||
void Map::removeAnnotations(const std::vector<uint32_t>& annotations) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
auto result = annotationManager->removeAnnotations(annotations, *this);
|
||||
updateAnnotationTiles(result);
|
||||
invokeTask([=] {
|
||||
auto result = annotationManager->removeAnnotations(annotations, *this);
|
||||
updateAnnotationTiles(result);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) const {
|
||||
std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
return annotationManager->getAnnotationsInBounds(bounds, *this);
|
||||
return invokeSyncTask([&] {
|
||||
return annotationManager->getAnnotationsInBounds(bounds, *this);
|
||||
});
|
||||
}
|
||||
|
||||
LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) const {
|
||||
LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
return annotationManager->getBoundsForAnnotations(annotations);
|
||||
return invokeSyncTask([&] {
|
||||
return annotationManager->getBoundsForAnnotations(annotations);
|
||||
});
|
||||
}
|
||||
|
||||
void Map::updateAnnotationTiles(const std::vector<Tile::ID>& ids) {
|
||||
assert(Environment::currentlyOn(ThreadType::Main));
|
||||
assert(Environment::currentlyOn(ThreadType::Map));
|
||||
for (const auto &source : activeSources) {
|
||||
if (source->info.type == SourceType::Annotations) {
|
||||
source->source->invalidateTiles(*this, ids);
|
||||
|
||||
Reference in New Issue
Block a user