├── usage.gif
├── search.gif
├── src
└── Contents
│ ├── Sketch
│ ├── main.cocoascript
│ ├── manifest.json
│ ├── MochaJSDelegate.js
│ ├── baidu.js
│ ├── google.js
│ ├── mapbox.js
│ └── common.js
│ └── Resources
│ ├── mapbox.html
│ ├── google.html
│ └── baidu.html
├── MapCreator.sketchplugin
└── Contents
│ ├── Sketch
│ ├── main.cocoascript
│ ├── manifest.json
│ ├── MochaJSDelegate.js
│ ├── baidu.js
│ ├── google.js
│ ├── mapbox.js
│ └── common.js
│ └── Resources
│ ├── mapbox.html
│ ├── google.html
│ └── baidu.html
├── appcast.xml
└── README.md
/usage.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/terence55/sketch-map-creator/HEAD/usage.gif
--------------------------------------------------------------------------------
/search.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/terence55/sketch-map-creator/HEAD/search.gif
--------------------------------------------------------------------------------
/src/Contents/Sketch/main.cocoascript:
--------------------------------------------------------------------------------
1 | @import "baidu.js";
2 | @import "mapbox.js";
3 | @import "google.js";
4 |
5 | function commandCreateBaiduMap(context) {
6 | var map = new BaiduMap();
7 | map.createMap(context);
8 | }
9 |
10 | function commandCreateMapboxMap(context) {
11 | var map = new Mapbox();
12 | map.createMap(context);
13 | }
14 |
15 | function commandCreateGoogleMap(context) {
16 | var map = new Google();
17 | map.createMap(context);
18 | }
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/main.cocoascript:
--------------------------------------------------------------------------------
1 | @import "baidu.js";
2 | @import "mapbox.js";
3 | @import "google.js";
4 |
5 | function commandCreateBaiduMap(context) {
6 | var map = new BaiduMap();
7 | map.createMap(context);
8 | }
9 |
10 | function commandCreateMapboxMap(context) {
11 | var map = new Mapbox();
12 | map.createMap(context);
13 | }
14 |
15 | function commandCreateGoogleMap(context) {
16 | var map = new Google();
17 | map.createMap(context);
18 | }
--------------------------------------------------------------------------------
/appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Map Creator
5 | https://github.com/terence55/sketch-map-creator
6 | Plugin to visually create static map(BaiduMap, MapBox, GoogleMap) with custom options
7 | en
8 | -
9 | Version 1.2.1
10 |
11 |
13 | Plugin to visually create static map(BaiduMap, MapBox, GoogleMap) with custom options
14 |
15 | ]]>
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Map Creator for Sketch
2 |
3 | ## Features (v1.2.1)
4 |
5 | - Plugin for Sketch to create a static map with custom options.
6 | - ***Visual selection for map center and zoom level supported(New feature).***
7 | - BaiduMap, MapBox and ***GoogleMap(new)*** have been supported now.
8 | - Easy to extend for other map services.
9 | - ***Support location search(New feature).***
10 |
11 | ***Now in latest version, you can select layer in Sketch 52+ correctly.***
12 |
13 | ## Installation
14 |
15 | - [Download](https://codeload.github.com/terence55/sketch-map-creator/zip/1.2.1) and unzip.
16 | - Open the file 'MapCreator.sketchplugin' for auto installation.
17 |
18 | ## Usage
19 |
20 | - Select a shape layer.
21 | - Choose the map you need.
22 | - Move map to target the center you want, zoom in/out with mouse wheel or buttons on map. You can also change map type in MapBox and GoogleMap.
23 | - Done.
24 |
25 | 
26 |
27 | ### Location Search
28 |
29 | 
30 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "author" : "Terence Wu",
3 | "bundleVersion" : 5,
4 | "commands" : [
5 | {
6 | "script" : "main.cocoascript",
7 | "name" : "Create Baidu Map",
8 | "handler" : "commandCreateBaiduMap",
9 | "identifier" : "commandCreateBaiduMap"
10 | },
11 | {
12 | "script" : "main.cocoascript",
13 | "name" : "Create Mapbox Map",
14 | "handler" : "commandCreateMapboxMap",
15 | "identifier" : "commandCreateMapboxMap"
16 | },
17 | {
18 | "script" : "main.cocoascript",
19 | "name" : "Create Google Map",
20 | "handler" : "commandCreateGoogleMap",
21 | "identifier" : "commandCreateGoogleMap"
22 | }
23 | ],
24 | "menu" : {
25 | "items" : [
26 | "commandCreateBaiduMap",
27 | "commandCreateMapboxMap",
28 | "commandCreateGoogleMap"
29 | ],
30 | "title" : "Map Creator"
31 | },
32 | "homepage" : "https://github.com/terence55/sketch-map-creator",
33 | "identifier" : "io.terence.sketch.mapcreator",
34 | "appcast": "https://raw.githubusercontent.com/terence55/sketch-map-creator/master/appcast.xml",
35 | "version" : "1.2.1",
36 | "description" : "Plugin to visually create static map(BaiduMap, MapBox, GoogleMap) with custom options",
37 | "authorEmail" : "trence320@163.com",
38 | "name" : "Map Creator"
39 | }
40 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "author" : "Terence Wu",
3 | "bundleVersion" : 5,
4 | "commands" : [
5 | {
6 | "script" : "main.cocoascript",
7 | "name" : "Create Baidu Map",
8 | "handler" : "commandCreateBaiduMap",
9 | "identifier" : "commandCreateBaiduMap"
10 | },
11 | {
12 | "script" : "main.cocoascript",
13 | "name" : "Create Mapbox Map",
14 | "handler" : "commandCreateMapboxMap",
15 | "identifier" : "commandCreateMapboxMap"
16 | },
17 | {
18 | "script" : "main.cocoascript",
19 | "name" : "Create Google Map",
20 | "handler" : "commandCreateGoogleMap",
21 | "identifier" : "commandCreateGoogleMap"
22 | }
23 | ],
24 | "menu" : {
25 | "items" : [
26 | "commandCreateBaiduMap",
27 | "commandCreateMapboxMap",
28 | "commandCreateGoogleMap"
29 | ],
30 | "title" : "Map Creator"
31 | },
32 | "homepage" : "https://github.com/terence55/sketch-map-creator",
33 | "identifier" : "io.terence.sketch.mapcreator",
34 | "appcast": "https://raw.githubusercontent.com/terence55/sketch-map-creator/master/appcast.xml",
35 | "version" : "1.2.1",
36 | "description" : "Plugin to visually create static map(BaiduMap, MapBox, GoogleMap) with custom options",
37 | "authorEmail" : "trence320@163.com",
38 | "name" : "Map Creator"
39 | }
40 |
--------------------------------------------------------------------------------
/src/Contents/Resources/mapbox.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 | Mapbox
12 |
13 |
14 |
15 |
16 |
72 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Resources/mapbox.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
9 |
10 |
11 | Mapbox
12 |
13 |
14 |
15 |
16 |
72 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/MochaJSDelegate.js:
--------------------------------------------------------------------------------
1 | //
2 | // MochaJSDelegate.js
3 | // MochaJSDelegate
4 | //
5 | // Created by Matt Curtis
6 | // Copyright (c) 2015. All rights reserved.
7 | //
8 |
9 | var MochaJSDelegate = function(selectorHandlerDict){
10 | var uniqueClassName = "MochaJSDelegate_DynamicClass_" + NSUUID.UUID().UUIDString();
11 |
12 | var delegateClassDesc = MOClassDescription.allocateDescriptionForClassWithName_superclass_(uniqueClassName, NSObject);
13 |
14 | delegateClassDesc.registerClass();
15 |
16 | // Handler storage
17 |
18 | var handlers = {};
19 |
20 | // Define interface
21 |
22 | this.setHandlerForSelector = function(selectorString, func){
23 | var handlerHasBeenSet = (selectorString in handlers);
24 | var selector = NSSelectorFromString(selectorString);
25 |
26 | handlers[selectorString] = func;
27 |
28 | if(!handlerHasBeenSet){
29 | /*
30 | For some reason, Mocha acts weird about arguments:
31 | https://github.com/logancollins/Mocha/issues/28
32 | We have to basically create a dynamic handler with a likewise dynamic number of predefined arguments.
33 | */
34 |
35 | var dynamicHandler = function(){
36 | var functionToCall = handlers[selectorString];
37 |
38 | if(!functionToCall) return;
39 |
40 | return functionToCall.apply(delegateClassDesc, arguments);
41 | };
42 |
43 | var args = [], regex = /:/g;
44 | while(match = regex.exec(selectorString)) args.push("arg"+args.length);
45 |
46 | dynamicFunction = eval("(function("+args.join(",")+"){ return dynamicHandler.apply(this, arguments); })");
47 |
48 | delegateClassDesc.addInstanceMethodWithSelector_function_(selector, dynamicFunction);
49 | }
50 | };
51 |
52 | this.removeHandlerForSelector = function(selectorString){
53 | delete handlers[selectorString];
54 | };
55 |
56 | this.getHandlerForSelector = function(selectorString){
57 | return handlers[selectorString];
58 | };
59 |
60 | this.getAllHandlers = function(){
61 | return handlers;
62 | };
63 |
64 | this.getClass = function(){
65 | return NSClassFromString(uniqueClassName);
66 | };
67 |
68 | this.getClassInstance = function(){
69 | return NSClassFromString(uniqueClassName).new();
70 | };
71 |
72 | // Conveience
73 |
74 | if(typeof selectorHandlerDict == "object"){
75 | for(var selectorString in selectorHandlerDict){
76 | this.setHandlerForSelector(selectorString, selectorHandlerDict[selectorString]);
77 | }
78 | }
79 | };
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/MochaJSDelegate.js:
--------------------------------------------------------------------------------
1 | //
2 | // MochaJSDelegate.js
3 | // MochaJSDelegate
4 | //
5 | // Created by Matt Curtis
6 | // Copyright (c) 2015. All rights reserved.
7 | //
8 |
9 | var MochaJSDelegate = function(selectorHandlerDict){
10 | var uniqueClassName = "MochaJSDelegate_DynamicClass_" + NSUUID.UUID().UUIDString();
11 |
12 | var delegateClassDesc = MOClassDescription.allocateDescriptionForClassWithName_superclass_(uniqueClassName, NSObject);
13 |
14 | delegateClassDesc.registerClass();
15 |
16 | // Handler storage
17 |
18 | var handlers = {};
19 |
20 | // Define interface
21 |
22 | this.setHandlerForSelector = function(selectorString, func){
23 | var handlerHasBeenSet = (selectorString in handlers);
24 | var selector = NSSelectorFromString(selectorString);
25 |
26 | handlers[selectorString] = func;
27 |
28 | if(!handlerHasBeenSet){
29 | /*
30 | For some reason, Mocha acts weird about arguments:
31 | https://github.com/logancollins/Mocha/issues/28
32 | We have to basically create a dynamic handler with a likewise dynamic number of predefined arguments.
33 | */
34 |
35 | var dynamicHandler = function(){
36 | var functionToCall = handlers[selectorString];
37 |
38 | if(!functionToCall) return;
39 |
40 | return functionToCall.apply(delegateClassDesc, arguments);
41 | };
42 |
43 | var args = [], regex = /:/g;
44 | while(match = regex.exec(selectorString)) args.push("arg"+args.length);
45 |
46 | dynamicFunction = eval("(function("+args.join(",")+"){ return dynamicHandler.apply(this, arguments); })");
47 |
48 | delegateClassDesc.addInstanceMethodWithSelector_function_(selector, dynamicFunction);
49 | }
50 | };
51 |
52 | this.removeHandlerForSelector = function(selectorString){
53 | delete handlers[selectorString];
54 | };
55 |
56 | this.getHandlerForSelector = function(selectorString){
57 | return handlers[selectorString];
58 | };
59 |
60 | this.getAllHandlers = function(){
61 | return handlers;
62 | };
63 |
64 | this.getClass = function(){
65 | return NSClassFromString(uniqueClassName);
66 | };
67 |
68 | this.getClassInstance = function(){
69 | return NSClassFromString(uniqueClassName).new();
70 | };
71 |
72 | // Conveience
73 |
74 | if(typeof selectorHandlerDict == "object"){
75 | for(var selectorString in selectorHandlerDict){
76 | this.setHandlerForSelector(selectorString, selectorHandlerDict[selectorString]);
77 | }
78 | }
79 | };
--------------------------------------------------------------------------------
/src/Contents/Resources/google.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 | GoogleMap
21 |
22 |
23 |
24 |
25 |
26 |
99 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Resources/google.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
19 |
20 | GoogleMap
21 |
22 |
23 |
24 |
25 |
26 |
99 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/baidu.js:
--------------------------------------------------------------------------------
1 | /**
2 | * baidu.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 | @import "MochaJSDelegate.js";
9 |
10 | function BaiduMap() {}
11 |
12 | BaiduMap.prototype.prefix = 'baidu';
13 | BaiduMap.prototype.maxWidth = 512;
14 | BaiduMap.prototype.maxHeight = 512;
15 | BaiduMap.prototype.ak = '4yWbU5UAZzPq3zG136ioc188jR1p6j0t';
16 |
17 | BaiduMap.prototype.createMap = function (context) {
18 | if (!checkLayer(context.selection)) {
19 | return;
20 | }
21 | var viewIndex = [];
22 | var dialog = this.buildOptionDialog(viewIndex, context);
23 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
24 | if (!options) {
25 | return;
26 | }
27 | var shouldRemember = getOption('remember', 0, this.prefix);
28 | if (shouldRemember == 1) {
29 | setOption('lng', this.centerLng, this.prefix);
30 | setOption('lat', this.centerLat, this.prefix);
31 | setOption('zoom', this.zoom, this.prefix);
32 | }
33 | var layer = context.selection[0];
34 | var layerSizes = layer.frame();
35 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
36 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
37 | var imageUrl = 'https://api.map.baidu.com/staticimage/v2?center=' + encodeURIComponent(this.centerLng + ',' + this.centerLat) + '&width=' + width + '&height=' + height + '&zoom=' + (parseInt(this.zoom)) + '&scale=2©right=1&ak=' + this.ak;
38 | fillLayer(context, imageUrl, layer);
39 | }
40 |
41 | BaiduMap.prototype.buildOptionDialog = function (viewIndex, context) {
42 | var shouldRemember = getOption('remember', 0, this.prefix);
43 |
44 | var dialogWindow = NSAlert.alloc().init();
45 | dialogWindow.setMessageText(tipsTargetCenter);
46 | var dialogContent = NSView.alloc().init();
47 | dialogContent.setFlipped(true);
48 | dialogContent.frame = NSMakeRect(0, 0, 800, 400);
49 | dialogWindow.accessoryView = dialogContent;
50 |
51 | dialogWindow.addButtonWithTitle('OK');
52 | dialogWindow.addButtonWithTitle('Cancel');
53 |
54 | var webView = createWebView('baidu.html', context, NSMakeRect(0, 0, 800, 350));
55 | var windowObject = webView.windowScriptObject();
56 | var self = this;
57 | var delegate = new MochaJSDelegate({
58 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
59 | if (shouldRemember == 1) {
60 | var options = {
61 | center: {
62 | lng: parseFloat(getOption('lng', 0, self.prefix)),
63 | lat: parseFloat(getOption('lat', 0, self.prefix))
64 | },
65 | zoom: parseInt(getOption('zoom', 11, self.prefix))
66 | };
67 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
68 | }
69 | }),
70 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
71 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
72 | var hash = parseHash(locationHash);
73 | self.centerLng = hash.centerLng;
74 | self.centerLat = hash.centerLat;
75 | self.zoom = hash.zoom;
76 | })
77 | });
78 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
79 | dialogContent.addSubview(webView);
80 |
81 | var checkTag = 1;
82 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 360, 200, 20), checkTag);
83 | dialogContent.addSubview(remember);
84 |
85 | viewIndex.push({
86 | key: 'remember',
87 | index: checkTag,
88 | type: 'string'
89 | });
90 |
91 | return dialogWindow;
92 | }
93 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/baidu.js:
--------------------------------------------------------------------------------
1 | /**
2 | * baidu.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 | @import "MochaJSDelegate.js";
9 |
10 | function BaiduMap() {}
11 |
12 | BaiduMap.prototype.prefix = 'baidu';
13 | BaiduMap.prototype.maxWidth = 512;
14 | BaiduMap.prototype.maxHeight = 512;
15 | BaiduMap.prototype.ak = '4yWbU5UAZzPq3zG136ioc188jR1p6j0t';
16 |
17 | BaiduMap.prototype.createMap = function (context) {
18 | if (!checkLayer(context.selection)) {
19 | return;
20 | }
21 | var viewIndex = [];
22 | var dialog = this.buildOptionDialog(viewIndex, context);
23 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
24 | if (!options) {
25 | return;
26 | }
27 | var shouldRemember = getOption('remember', 0, this.prefix);
28 | if (shouldRemember == 1) {
29 | setOption('lng', this.centerLng, this.prefix);
30 | setOption('lat', this.centerLat, this.prefix);
31 | setOption('zoom', this.zoom, this.prefix);
32 | }
33 | var layer = context.selection[0];
34 | var layerSizes = layer.frame();
35 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
36 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
37 | var imageUrl = 'https://api.map.baidu.com/staticimage/v2?center=' + encodeURIComponent(this.centerLng + ',' + this.centerLat) + '&width=' + width + '&height=' + height + '&zoom=' + (parseInt(this.zoom)) + '&scale=2©right=1&ak=' + this.ak;
38 | fillLayer(context, imageUrl, layer);
39 | }
40 |
41 | BaiduMap.prototype.buildOptionDialog = function (viewIndex, context) {
42 | var shouldRemember = getOption('remember', 0, this.prefix);
43 |
44 | var dialogWindow = NSAlert.alloc().init();
45 | dialogWindow.setMessageText(tipsTargetCenter);
46 | var dialogContent = NSView.alloc().init();
47 | dialogContent.setFlipped(true);
48 | dialogContent.frame = NSMakeRect(0, 0, 800, 400);
49 | dialogWindow.accessoryView = dialogContent;
50 |
51 | dialogWindow.addButtonWithTitle('OK');
52 | dialogWindow.addButtonWithTitle('Cancel');
53 |
54 | var webView = createWebView('baidu.html', context, NSMakeRect(0, 0, 800, 350));
55 | var windowObject = webView.windowScriptObject();
56 | var self = this;
57 | var delegate = new MochaJSDelegate({
58 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
59 | if (shouldRemember == 1) {
60 | var options = {
61 | center: {
62 | lng: parseFloat(getOption('lng', 0, self.prefix)),
63 | lat: parseFloat(getOption('lat', 0, self.prefix))
64 | },
65 | zoom: parseInt(getOption('zoom', 11, self.prefix))
66 | };
67 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
68 | }
69 | }),
70 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
71 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
72 | var hash = parseHash(locationHash);
73 | self.centerLng = hash.centerLng;
74 | self.centerLat = hash.centerLat;
75 | self.zoom = hash.zoom;
76 | })
77 | });
78 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
79 | dialogContent.addSubview(webView);
80 |
81 | var checkTag = 1;
82 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 360, 200, 20), checkTag);
83 | dialogContent.addSubview(remember);
84 |
85 | viewIndex.push({
86 | key: 'remember',
87 | index: checkTag,
88 | type: 'string'
89 | });
90 |
91 | return dialogWindow;
92 | }
93 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/google.js:
--------------------------------------------------------------------------------
1 | /**
2 | * google.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 |
9 | function Google() { }
10 |
11 | Google.prototype.prefix = 'google';
12 | Google.prototype.maxWidth = 640;
13 | Google.prototype.maxHeight = 640;
14 | Google.prototype.types = [
15 | 'roadmap',
16 | 'satellite',
17 | 'terrain',
18 | 'hybrid'
19 | ];
20 | Google.prototype.ak = 'AIzaSyApdHVaG_6lBal7DLBPVjzQ2lvlSLfykc8';
21 |
22 | Google.prototype.createMap = function (context) {
23 | if (!checkLayer(context.selection)) {
24 | return;
25 | }
26 | var app = NSApplication.sharedApplication();
27 | var viewIndex = [];
28 | var dialog = this.buildOptionDialog(viewIndex, context);
29 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
30 | if (!options) {
31 | return;
32 | }
33 | var shouldRemember = getOption('remember', 0, this.prefix);
34 | if (shouldRemember == 1) {
35 | setOption('lng', this.centerLng, this.prefix);
36 | setOption('lat', this.centerLat, this.prefix);
37 | setOption('zoom', this.zoom, this.prefix);
38 | }
39 | var layer = context.selection[0];
40 | var layerSizes = layer.frame();
41 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
42 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
43 | var imageUrl = 'https://maps.googleapis.com/maps/api/staticmap?center=' + this.centerLat + ',' + this.centerLng + '&zoom=' + this.zoom + '&size=' + width + 'x' + height + '&maptype=' + options.type + '&scale=2&key=' + this.ak;
44 | fillLayer(context, imageUrl, layer);
45 | }
46 |
47 | Google.prototype.buildOptionDialog = function (viewIndex, context) {
48 | var shouldRemember = getOption('remember', 0, this.prefix);
49 |
50 | var dialogWindow = NSAlert.alloc().init();
51 | dialogWindow.setMessageText(tipsTargetCenter);
52 | var dialogContent = NSView.alloc().init();
53 | dialogContent.setFlipped(true);
54 | dialogContent.frame = NSMakeRect(0, 0, 500, 430);
55 | dialogWindow.accessoryView = dialogContent;
56 |
57 | dialogWindow.addButtonWithTitle('OK');
58 | dialogWindow.addButtonWithTitle('Cancel');
59 |
60 | var typeIndex = getOption('type', 0, this.prefix);
61 | var webView = createWebView('google.html', context, NSMakeRect(0, 0, 500, 350));
62 | var windowObject = webView.windowScriptObject();
63 | var self = this;
64 | var delegate = new MochaJSDelegate({
65 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
66 | if (shouldRemember == 1) {
67 | var options = {
68 | center: {
69 | lng: parseFloat(getOption('lng', 0, self.prefix)),
70 | lat: parseFloat(getOption('lat', 0, self.prefix))
71 | },
72 | zoom: parseInt(getOption('zoom', 11, self.prefix))
73 | };
74 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
75 | var mapType = self.types[typeIndex];
76 | windowObject.evaluateWebScript('setType("' + mapType + '")');
77 | }
78 | }),
79 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
80 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
81 | var hash = parseHash(locationHash);
82 | self.centerLng = hash.centerLng;
83 | self.centerLat = hash.centerLat;
84 | self.zoom = hash.zoom;
85 | })
86 | });
87 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
88 | dialogContent.addSubview(webView);
89 |
90 | var typeLabel = createLabel('Select map type', NSMakeRect(0, 360, 100, 20));
91 | dialogContent.addSubview(typeLabel);
92 |
93 | var typeTag = 1;
94 | var type = createSelect(this.types, shouldRemember == 0 ? 0 : getOption('type', 0, this.prefix), NSMakeRect(120, 360, 200, 20), typeTag, function(sender) {
95 | var mapType = self.types[sender.indexOfSelectedItem()];
96 | windowObject.evaluateWebScript('setType("' + mapType + '")');
97 | });
98 | dialogContent.addSubview(type);
99 |
100 | var checkTag = 2;
101 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 390, 150, 20), checkTag);
102 | dialogContent.addSubview(remember);
103 |
104 | viewIndex.push({
105 | key: 'type',
106 | index: typeTag,
107 | type: 'select'
108 | });
109 |
110 | viewIndex.push({
111 | key: 'remember',
112 | index: checkTag,
113 | type: 'string'
114 | });
115 |
116 | return dialogWindow;
117 | }
118 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/google.js:
--------------------------------------------------------------------------------
1 | /**
2 | * google.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 |
9 | function Google() { }
10 |
11 | Google.prototype.prefix = 'google';
12 | Google.prototype.maxWidth = 640;
13 | Google.prototype.maxHeight = 640;
14 | Google.prototype.types = [
15 | 'roadmap',
16 | 'satellite',
17 | 'terrain',
18 | 'hybrid'
19 | ];
20 | Google.prototype.ak = 'AIzaSyApdHVaG_6lBal7DLBPVjzQ2lvlSLfykc8';
21 |
22 | Google.prototype.createMap = function (context) {
23 | if (!checkLayer(context.selection)) {
24 | return;
25 | }
26 | var app = NSApplication.sharedApplication();
27 | var viewIndex = [];
28 | var dialog = this.buildOptionDialog(viewIndex, context);
29 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
30 | if (!options) {
31 | return;
32 | }
33 | var shouldRemember = getOption('remember', 0, this.prefix);
34 | if (shouldRemember == 1) {
35 | setOption('lng', this.centerLng, this.prefix);
36 | setOption('lat', this.centerLat, this.prefix);
37 | setOption('zoom', this.zoom, this.prefix);
38 | }
39 | var layer = context.selection[0];
40 | var layerSizes = layer.frame();
41 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
42 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
43 | var imageUrl = 'https://maps.googleapis.com/maps/api/staticmap?center=' + this.centerLat + ',' + this.centerLng + '&zoom=' + this.zoom + '&size=' + width + 'x' + height + '&maptype=' + options.type + '&scale=2&key=' + this.ak;
44 | fillLayer(context, imageUrl, layer);
45 | }
46 |
47 | Google.prototype.buildOptionDialog = function (viewIndex, context) {
48 | var shouldRemember = getOption('remember', 0, this.prefix);
49 |
50 | var dialogWindow = NSAlert.alloc().init();
51 | dialogWindow.setMessageText(tipsTargetCenter);
52 | var dialogContent = NSView.alloc().init();
53 | dialogContent.setFlipped(true);
54 | dialogContent.frame = NSMakeRect(0, 0, 500, 430);
55 | dialogWindow.accessoryView = dialogContent;
56 |
57 | dialogWindow.addButtonWithTitle('OK');
58 | dialogWindow.addButtonWithTitle('Cancel');
59 |
60 | var typeIndex = getOption('type', 0, this.prefix);
61 | var webView = createWebView('google.html', context, NSMakeRect(0, 0, 500, 350));
62 | var windowObject = webView.windowScriptObject();
63 | var self = this;
64 | var delegate = new MochaJSDelegate({
65 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
66 | if (shouldRemember == 1) {
67 | var options = {
68 | center: {
69 | lng: parseFloat(getOption('lng', 0, self.prefix)),
70 | lat: parseFloat(getOption('lat', 0, self.prefix))
71 | },
72 | zoom: parseInt(getOption('zoom', 11, self.prefix))
73 | };
74 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
75 | var mapType = self.types[typeIndex];
76 | windowObject.evaluateWebScript('setType("' + mapType + '")');
77 | }
78 | }),
79 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
80 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
81 | var hash = parseHash(locationHash);
82 | self.centerLng = hash.centerLng;
83 | self.centerLat = hash.centerLat;
84 | self.zoom = hash.zoom;
85 | })
86 | });
87 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
88 | dialogContent.addSubview(webView);
89 |
90 | var typeLabel = createLabel('Select map type', NSMakeRect(0, 360, 100, 20));
91 | dialogContent.addSubview(typeLabel);
92 |
93 | var typeTag = 1;
94 | var type = createSelect(this.types, shouldRemember == 0 ? 0 : getOption('type', 0, this.prefix), NSMakeRect(120, 360, 200, 20), typeTag, function(sender) {
95 | var mapType = self.types[sender.indexOfSelectedItem()];
96 | windowObject.evaluateWebScript('setType("' + mapType + '")');
97 | });
98 | dialogContent.addSubview(type);
99 |
100 | var checkTag = 2;
101 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 390, 150, 20), checkTag);
102 | dialogContent.addSubview(remember);
103 |
104 | viewIndex.push({
105 | key: 'type',
106 | index: typeTag,
107 | type: 'select'
108 | });
109 |
110 | viewIndex.push({
111 | key: 'remember',
112 | index: checkTag,
113 | type: 'string'
114 | });
115 |
116 | return dialogWindow;
117 | }
118 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/mapbox.js:
--------------------------------------------------------------------------------
1 | /**
2 | * mapbox.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 |
9 | function Mapbox() { }
10 |
11 | Mapbox.prototype.prefix = 'mapbox';
12 | Mapbox.prototype.maxWidth = 1280;
13 | Mapbox.prototype.maxHeight = 1280;
14 | Mapbox.prototype.types = [
15 | 'streets',
16 | 'light',
17 | 'dark',
18 | 'satellite',
19 | 'streets-satellite',
20 | 'wheatpaste',
21 | 'streets-basic',
22 | 'comic',
23 | 'outdoors',
24 | 'run-bike-hike',
25 | 'pencil',
26 | 'pirates',
27 | 'emerald',
28 | 'high-contrast'
29 | ];
30 | Mapbox.prototype.ak = 'pk.eyJ1IjoidHJlbmNlMzIwIiwiYSI6ImNqNjRobjF0czFrZGMzMnBvN3VzYzQxenMifQ.BJml_qE3BhBJ2bPodjwfeg';
31 |
32 | Mapbox.prototype.createMap = function (context) {
33 | if (!checkLayer(context.selection)) {
34 | return;
35 | }
36 | var app = NSApplication.sharedApplication();
37 | var viewIndex = [];
38 | var dialog = this.buildOptionDialog(viewIndex, context);
39 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
40 | if (!options) {
41 | return;
42 | }
43 | var shouldRemember = getOption('remember', 0, this.prefix);
44 | if (shouldRemember == 1) {
45 | setOption('lng', this.centerLng, this.prefix);
46 | setOption('lat', this.centerLat, this.prefix);
47 | setOption('zoom', this.zoom, this.prefix);
48 | }
49 | var layer = context.selection[0];
50 | var layerSizes = layer.frame();
51 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
52 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
53 | var imageUrl = 'https://api.mapbox.com/v4/mapbox.' + options.type + '/' + this.centerLng + ',' + this.centerLat + ',' + this.zoom + '/' + width + 'x' + height + '.jpg90?access_token=' + this.ak;
54 | fillLayer(context, imageUrl, layer);
55 | }
56 |
57 | Mapbox.prototype.buildOptionDialog = function (viewIndex, context) {
58 | var shouldRemember = getOption('remember', 0, this.prefix);
59 |
60 | var dialogWindow = NSAlert.alloc().init();
61 | dialogWindow.setMessageText(tipsTargetCenter);
62 | var dialogContent = NSView.alloc().init();
63 | dialogContent.setFlipped(true);
64 | dialogContent.frame = NSMakeRect(0, 0, 500, 430);
65 | dialogWindow.accessoryView = dialogContent;
66 |
67 | dialogWindow.addButtonWithTitle('OK');
68 | dialogWindow.addButtonWithTitle('Cancel');
69 |
70 | var typeIndex = getOption('type', 0, this.prefix);
71 | var webView = createWebView('mapbox.html', context, NSMakeRect(0, 0, 500, 350));
72 | var windowObject = webView.windowScriptObject();
73 | var self = this;
74 | var delegate = new MochaJSDelegate({
75 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
76 | if (shouldRemember == 1) {
77 | var options = {
78 | center: {
79 | lng: parseFloat(getOption('lng', 0, self.prefix)),
80 | lat: parseFloat(getOption('lat', 0, self.prefix))
81 | },
82 | zoom: parseInt(getOption('zoom', 11, self.prefix))
83 | };
84 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
85 | var mapType = 'mapbox.' + self.types[typeIndex];
86 | windowObject.evaluateWebScript('setType("' + mapType + '")');
87 | }
88 | }),
89 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
90 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
91 | var hash = parseHash(locationHash);
92 | self.centerLng = hash.centerLng;
93 | self.centerLat = hash.centerLat;
94 | self.zoom = hash.zoom;
95 | })
96 | });
97 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
98 | dialogContent.addSubview(webView);
99 |
100 | var typeLabel = createLabel('Select map type', NSMakeRect(0, 360, 100, 20));
101 | dialogContent.addSubview(typeLabel);
102 |
103 | var typeTag = 1;
104 | var type = createSelect(this.types, shouldRemember == 0 ? 0 : getOption('type', 0, this.prefix), NSMakeRect(120, 360, 200, 20), typeTag, function(sender) {
105 | var mapType = 'mapbox.' + self.types[sender.indexOfSelectedItem()];
106 | windowObject.evaluateWebScript('setType("' + mapType + '")');
107 | });
108 | dialogContent.addSubview(type);
109 |
110 | var checkTag = 2;
111 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 390, 150, 20), checkTag);
112 | dialogContent.addSubview(remember);
113 |
114 | viewIndex.push({
115 | key: 'type',
116 | index: typeTag,
117 | type: 'select'
118 | });
119 |
120 | viewIndex.push({
121 | key: 'remember',
122 | index: checkTag,
123 | type: 'string'
124 | });
125 |
126 | return dialogWindow;
127 | }
128 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/mapbox.js:
--------------------------------------------------------------------------------
1 | /**
2 | * mapbox.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | @import "common.js";
8 |
9 | function Mapbox() { }
10 |
11 | Mapbox.prototype.prefix = 'mapbox';
12 | Mapbox.prototype.maxWidth = 1280;
13 | Mapbox.prototype.maxHeight = 1280;
14 | Mapbox.prototype.types = [
15 | 'streets',
16 | 'light',
17 | 'dark',
18 | 'satellite',
19 | 'streets-satellite',
20 | 'wheatpaste',
21 | 'streets-basic',
22 | 'comic',
23 | 'outdoors',
24 | 'run-bike-hike',
25 | 'pencil',
26 | 'pirates',
27 | 'emerald',
28 | 'high-contrast'
29 | ];
30 | Mapbox.prototype.ak = 'pk.eyJ1IjoidHJlbmNlMzIwIiwiYSI6ImNqNjRobjF0czFrZGMzMnBvN3VzYzQxenMifQ.BJml_qE3BhBJ2bPodjwfeg';
31 |
32 | Mapbox.prototype.createMap = function (context) {
33 | if (!checkLayer(context.selection)) {
34 | return;
35 | }
36 | var app = NSApplication.sharedApplication();
37 | var viewIndex = [];
38 | var dialog = this.buildOptionDialog(viewIndex, context);
39 | var options = handleDialog(dialog, viewIndex, this.prefix, dialog.runModal());
40 | if (!options) {
41 | return;
42 | }
43 | var shouldRemember = getOption('remember', 0, this.prefix);
44 | if (shouldRemember == 1) {
45 | setOption('lng', this.centerLng, this.prefix);
46 | setOption('lat', this.centerLat, this.prefix);
47 | setOption('zoom', this.zoom, this.prefix);
48 | }
49 | var layer = context.selection[0];
50 | var layerSizes = layer.frame();
51 | var width = Math.min(parseInt([layerSizes width]), this.maxWidth);
52 | var height = Math.min(parseInt([layerSizes height]), this.maxHeight);
53 | var imageUrl = 'https://api.mapbox.com/v4/mapbox.' + options.type + '/' + this.centerLng + ',' + this.centerLat + ',' + this.zoom + '/' + width + 'x' + height + '.jpg90?access_token=' + this.ak;
54 | fillLayer(context, imageUrl, layer);
55 | }
56 |
57 | Mapbox.prototype.buildOptionDialog = function (viewIndex, context) {
58 | var shouldRemember = getOption('remember', 0, this.prefix);
59 |
60 | var dialogWindow = NSAlert.alloc().init();
61 | dialogWindow.setMessageText(tipsTargetCenter);
62 | var dialogContent = NSView.alloc().init();
63 | dialogContent.setFlipped(true);
64 | dialogContent.frame = NSMakeRect(0, 0, 500, 430);
65 | dialogWindow.accessoryView = dialogContent;
66 |
67 | dialogWindow.addButtonWithTitle('OK');
68 | dialogWindow.addButtonWithTitle('Cancel');
69 |
70 | var typeIndex = getOption('type', 0, this.prefix);
71 | var webView = createWebView('mapbox.html', context, NSMakeRect(0, 0, 500, 350));
72 | var windowObject = webView.windowScriptObject();
73 | var self = this;
74 | var delegate = new MochaJSDelegate({
75 | "webView:didFinishLoadForFrame:" : (function(webView, webFrame) {
76 | if (shouldRemember == 1) {
77 | var options = {
78 | center: {
79 | lng: parseFloat(getOption('lng', 0, self.prefix)),
80 | lat: parseFloat(getOption('lat', 0, self.prefix))
81 | },
82 | zoom: parseInt(getOption('zoom', 11, self.prefix))
83 | };
84 | windowObject.evaluateWebScript('setOptions(' + JSON.stringify(options) + ')');
85 | var mapType = 'mapbox.' + self.types[typeIndex];
86 | windowObject.evaluateWebScript('setType("' + mapType + '")');
87 | }
88 | }),
89 | "webView:didChangeLocationWithinPageForFrame:" : (function(webView, webFrame) {
90 | var locationHash = windowObject.evaluateWebScript("window.location.hash");
91 | var hash = parseHash(locationHash);
92 | self.centerLng = hash.centerLng;
93 | self.centerLat = hash.centerLat;
94 | self.zoom = hash.zoom;
95 | })
96 | });
97 | webView.setFrameLoadDelegate_(delegate.getClassInstance());
98 | dialogContent.addSubview(webView);
99 |
100 | var typeLabel = createLabel('Select map type', NSMakeRect(0, 360, 100, 20));
101 | dialogContent.addSubview(typeLabel);
102 |
103 | var typeTag = 1;
104 | var type = createSelect(this.types, shouldRemember == 0 ? 0 : getOption('type', 0, this.prefix), NSMakeRect(120, 360, 200, 20), typeTag, function(sender) {
105 | var mapType = 'mapbox.' + self.types[sender.indexOfSelectedItem()];
106 | windowObject.evaluateWebScript('setType("' + mapType + '")');
107 | });
108 | dialogContent.addSubview(type);
109 |
110 | var checkTag = 2;
111 | var remember = createCheck('Remember my options', shouldRemember == 1, NSMakeRect(0, 390, 150, 20), checkTag);
112 | dialogContent.addSubview(remember);
113 |
114 | viewIndex.push({
115 | key: 'type',
116 | index: typeTag,
117 | type: 'select'
118 | });
119 |
120 | viewIndex.push({
121 | key: 'remember',
122 | index: checkTag,
123 | type: 'string'
124 | });
125 |
126 | return dialogWindow;
127 | }
128 |
--------------------------------------------------------------------------------
/src/Contents/Resources/baidu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
47 |
48 | BaiduMap
49 |
50 |
51 |
52 |
56 |
57 |
172 |
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Resources/baidu.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
47 |
48 | BaiduMap
49 |
50 |
51 |
52 |
56 |
57 |
172 |
--------------------------------------------------------------------------------
/src/Contents/Sketch/common.js:
--------------------------------------------------------------------------------
1 | /**
2 | * common.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | var pluginIdentifier = 'io.terence.sketch.mapcreator';
8 |
9 | var tipsTargetCenter = 'Move map to target the center you want';
10 |
11 | function checkLayer(selectedLayers) {
12 | var app = NSApplication.sharedApplication();
13 | if (!selectedLayers || selectedLayers.count() != 1) {
14 | app.displayDialog_withTitle('Please select exactly 1 shape layer.', 'Invalid shape layer selection');
15 | return false;
16 | }
17 | var layer = selectedLayers[0];
18 | var validSelection = true;
19 | if (MSApplicationMetadata.metadata().appVersion >= 52) {
20 | if (layer.edited === undefined) {
21 | validSelection = false;
22 | }
23 | } else if ([layer class] !== MSShapeGroup) {
24 | validSelection = false;
25 | }
26 | if (!validSelection) {
27 | app.displayDialog_withTitle('Your selection was a ' + [layer name] + ', that is not a shape layer. Please select a shape layer.', 'Invalid layer type');
28 | return false;
29 | }
30 | return true;
31 | }
32 |
33 | function createLabel(value, frame) {
34 | var textField = NSTextField.alloc().initWithFrame(frame);
35 | textField.setEditable(false);
36 | textField.setBordered(false);
37 | textField.setBackgroundColor(NSColor.colorWithRed_green_blue_alpha(0, 0, 0, 0));
38 | if (value) {
39 | textField.setStringValue(value);
40 | }
41 | return textField;
42 | }
43 |
44 | function createTextField(value, placeholder, frame, tag) {
45 | var textField = NSTextField.alloc().initWithFrame(frame);
46 | if (value) {
47 | textField.setStringValue(value);
48 | }
49 | if (placeholder) {
50 | textField.setPlaceholderString(placeholder);
51 | }
52 | textField.setTag(tag);
53 | return textField;
54 | }
55 |
56 | function createSelect(options, selectedIndex, frame, tag, onSelectChange) {
57 | var selIdx = selectedIndex || 0;
58 | var select = NSPopUpButton.alloc().initWithFrame(frame);
59 | var i;
60 | if (options) {
61 | select.addItemsWithTitles(options);
62 | select.selectItemAtIndex(selIdx);
63 | }
64 | select.setTag(tag);
65 | if (onSelectChange) {
66 | select.setCOSJSTargetFunction(onSelectChange);
67 | }
68 | return select;
69 | }
70 |
71 | function createCheck(title, checked, frame, tag) {
72 | var check = NSButton.alloc().initWithFrame(frame);
73 | check.setButtonType(NSSwitchButton);
74 | check.setBezelStyle(NSRoundedBezelStyle);
75 | check.setTitle(title);
76 | check.setState(checked == 0 ? NSOffState : NSOnState);
77 | check.setTag(tag);
78 | return check;
79 | }
80 |
81 | function createWebView(uri, context, frame) {
82 | var webView = WebView.alloc().initWithFrame(frame);
83 | webView.setMainFrameURL_(context.plugin.urlForResourceNamed(uri).path());
84 | return webView;
85 | }
86 |
87 | function fillLayer(context, imageUrl, layer) {
88 | var data = fetchImage(imageUrl);
89 | if (!data) {
90 | context.document.showMessage("Fetch map error, invalid request params");
91 | return;
92 | }
93 | var result = NSString.alloc().initWithData_encoding(data, NSUTF8StringEncoding);
94 | if (result) {
95 | context.document.showMessage("Fetch map error, invalid request params, error info: " + result);
96 | return;
97 | }
98 | var imageData = NSImage.alloc().initWithData(data);
99 | var fill = layer.style().fills().firstObject();
100 | fill.setFillType(4);
101 | if (MSApplicationMetadata.metadata().appVersion < 47) {
102 | fill.setImage(MSImageData.alloc().initWithImageConvertingColorSpace(imageData, false));
103 | } else {
104 | fill.setImage(MSImageData.alloc().initWithImage(imageData));
105 | }
106 | fill.setPatternFillType(1);
107 | context.document.showMessage("Map has been created");
108 | }
109 |
110 | function fetchImage(url) {
111 | var request = NSURLRequest.requestWithURL(NSURL.URLWithString(url));
112 | var response = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
113 | return response;
114 | }
115 |
116 | function handleDialog(dialog, viewIndex, prefix, responseCode) {
117 | saveOptions(dialog, viewIndex, prefix);
118 | if (responseCode == NSAlertFirstButtonReturn) {
119 | var result = {};
120 | var i;
121 | for (i = 0; i < viewIndex.length; i++) {
122 | if (viewIndex[i].type === 'select') {
123 | result[viewIndex[i].key] = dialog.accessoryView().viewWithTag(viewIndex[i].index).titleOfSelectedItem();
124 | } else if (viewIndex[i].type === 'string') {
125 | result[viewIndex[i].key] = dialog.accessoryView().viewWithTag(viewIndex[i].index).stringValue();
126 | }
127 | };
128 | return result;
129 | }
130 | return null;
131 | }
132 |
133 | function saveOptions(dialog, viewIndex, prefix) {
134 | var i;
135 | for (i = 0; i < viewIndex.length; i++) {
136 | if (viewIndex[i].type === 'select') {
137 | setOption(viewIndex[i].key, dialog.accessoryView().viewWithTag(viewIndex[i].index).indexOfSelectedItem(), prefix);
138 | } else if (viewIndex[i].type === 'string') {
139 | setOption(viewIndex[i].key, dialog.accessoryView().viewWithTag(viewIndex[i].index).stringValue(), prefix);
140 | }
141 | };
142 | }
143 |
144 | function setOption(key, value, prefix) {
145 | return setPreferences(prefix + '.' + key, value);
146 | }
147 |
148 | function getOption(key, defaultValue, prefix) {
149 | return getPreferences(prefix + '.' + key, defaultValue);
150 | }
151 |
152 | function getPreferences(key, defaultValue) {
153 | var userDefaults = NSUserDefaults.standardUserDefaults();
154 | if (!userDefaults.dictionaryForKey(pluginIdentifier)) {
155 | var defaultPreferences = NSMutableDictionary.alloc().init();
156 | userDefaults.setObject_forKey(defaultPreferences, pluginIdentifier);
157 | userDefaults.synchronize();
158 | }
159 | var value = userDefaults.dictionaryForKey(pluginIdentifier).objectForKey(key);
160 | return value === undefined ? defaultValue : value;
161 | }
162 |
163 | function setPreferences(key, value) {
164 | var userDefaults = NSUserDefaults.standardUserDefaults();
165 | var preferences;
166 | if (!userDefaults.dictionaryForKey(pluginIdentifier)) {
167 | preferences = NSMutableDictionary.alloc().init();
168 | } else {
169 | preferences = NSMutableDictionary.dictionaryWithDictionary(userDefaults.dictionaryForKey(pluginIdentifier));
170 | }
171 | preferences.setObject_forKey(value, key);
172 | userDefaults.setObject_forKey(preferences, pluginIdentifier);
173 | userDefaults.synchronize();
174 | }
175 |
176 | function parseHash(url) {
177 | url = url;
178 | var vars = {};
179 | var hashes = url.slice(url.indexOf('#') + 1).split('&');
180 | for(var i = 0; i < hashes.length; i++) {
181 | var hash = hashes[i].split('=');
182 | if(hash.length > 1) {
183 | vars[hash[0].toString()] = hash[1];
184 | } else {
185 | vars[hash[0].toString()] = null;
186 | }
187 | }
188 | return vars;
189 | }
--------------------------------------------------------------------------------
/MapCreator.sketchplugin/Contents/Sketch/common.js:
--------------------------------------------------------------------------------
1 | /**
2 | * common.js
3 | *
4 | * Copyright (c) 2017-present, Terence Wu.
5 | */
6 |
7 | var pluginIdentifier = 'io.terence.sketch.mapcreator';
8 |
9 | var tipsTargetCenter = 'Move map to target the center you want';
10 |
11 | function checkLayer(selectedLayers) {
12 | var app = NSApplication.sharedApplication();
13 | if (!selectedLayers || selectedLayers.count() != 1) {
14 | app.displayDialog_withTitle('Please select exactly 1 shape layer.', 'Invalid shape layer selection');
15 | return false;
16 | }
17 | var layer = selectedLayers[0];
18 | var validSelection = true;
19 | if (MSApplicationMetadata.metadata().appVersion >= 52) {
20 | if (layer.edited === undefined) {
21 | validSelection = false;
22 | }
23 | } else if ([layer class] !== MSShapeGroup) {
24 | validSelection = false;
25 | }
26 | if (!validSelection) {
27 | app.displayDialog_withTitle('Your selection was a ' + [layer name] + ', that is not a shape layer. Please select a shape layer.', 'Invalid layer type');
28 | return false;
29 | }
30 | return true;
31 | }
32 |
33 | function createLabel(value, frame) {
34 | var textField = NSTextField.alloc().initWithFrame(frame);
35 | textField.setEditable(false);
36 | textField.setBordered(false);
37 | textField.setBackgroundColor(NSColor.colorWithRed_green_blue_alpha(0, 0, 0, 0));
38 | if (value) {
39 | textField.setStringValue(value);
40 | }
41 | return textField;
42 | }
43 |
44 | function createTextField(value, placeholder, frame, tag) {
45 | var textField = NSTextField.alloc().initWithFrame(frame);
46 | if (value) {
47 | textField.setStringValue(value);
48 | }
49 | if (placeholder) {
50 | textField.setPlaceholderString(placeholder);
51 | }
52 | textField.setTag(tag);
53 | return textField;
54 | }
55 |
56 | function createSelect(options, selectedIndex, frame, tag, onSelectChange) {
57 | var selIdx = selectedIndex || 0;
58 | var select = NSPopUpButton.alloc().initWithFrame(frame);
59 | var i;
60 | if (options) {
61 | select.addItemsWithTitles(options);
62 | select.selectItemAtIndex(selIdx);
63 | }
64 | select.setTag(tag);
65 | if (onSelectChange) {
66 | select.setCOSJSTargetFunction(onSelectChange);
67 | }
68 | return select;
69 | }
70 |
71 | function createCheck(title, checked, frame, tag) {
72 | var check = NSButton.alloc().initWithFrame(frame);
73 | check.setButtonType(NSSwitchButton);
74 | check.setBezelStyle(NSRoundedBezelStyle);
75 | check.setTitle(title);
76 | check.setState(checked == 0 ? NSOffState : NSOnState);
77 | check.setTag(tag);
78 | return check;
79 | }
80 |
81 | function createWebView(uri, context, frame) {
82 | var webView = WebView.alloc().initWithFrame(frame);
83 | webView.setMainFrameURL_(context.plugin.urlForResourceNamed(uri).path());
84 | return webView;
85 | }
86 |
87 | function fillLayer(context, imageUrl, layer) {
88 | var data = fetchImage(imageUrl);
89 | if (!data) {
90 | context.document.showMessage("Fetch map error, invalid request params");
91 | return;
92 | }
93 | var result = NSString.alloc().initWithData_encoding(data, NSUTF8StringEncoding);
94 | if (result) {
95 | context.document.showMessage("Fetch map error, invalid request params, error info: " + result);
96 | return;
97 | }
98 | var imageData = NSImage.alloc().initWithData(data);
99 | var fill = layer.style().fills().firstObject();
100 | fill.setFillType(4);
101 | if (MSApplicationMetadata.metadata().appVersion < 47) {
102 | fill.setImage(MSImageData.alloc().initWithImageConvertingColorSpace(imageData, false));
103 | } else {
104 | fill.setImage(MSImageData.alloc().initWithImage(imageData));
105 | }
106 | fill.setPatternFillType(1);
107 | context.document.showMessage("Map has been created");
108 | }
109 |
110 | function fetchImage(url) {
111 | var request = NSURLRequest.requestWithURL(NSURL.URLWithString(url));
112 | var response = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null);
113 | return response;
114 | }
115 |
116 | function handleDialog(dialog, viewIndex, prefix, responseCode) {
117 | saveOptions(dialog, viewIndex, prefix);
118 | if (responseCode == NSAlertFirstButtonReturn) {
119 | var result = {};
120 | var i;
121 | for (i = 0; i < viewIndex.length; i++) {
122 | if (viewIndex[i].type === 'select') {
123 | result[viewIndex[i].key] = dialog.accessoryView().viewWithTag(viewIndex[i].index).titleOfSelectedItem();
124 | } else if (viewIndex[i].type === 'string') {
125 | result[viewIndex[i].key] = dialog.accessoryView().viewWithTag(viewIndex[i].index).stringValue();
126 | }
127 | };
128 | return result;
129 | }
130 | return null;
131 | }
132 |
133 | function saveOptions(dialog, viewIndex, prefix) {
134 | var i;
135 | for (i = 0; i < viewIndex.length; i++) {
136 | if (viewIndex[i].type === 'select') {
137 | setOption(viewIndex[i].key, dialog.accessoryView().viewWithTag(viewIndex[i].index).indexOfSelectedItem(), prefix);
138 | } else if (viewIndex[i].type === 'string') {
139 | setOption(viewIndex[i].key, dialog.accessoryView().viewWithTag(viewIndex[i].index).stringValue(), prefix);
140 | }
141 | };
142 | }
143 |
144 | function setOption(key, value, prefix) {
145 | return setPreferences(prefix + '.' + key, value);
146 | }
147 |
148 | function getOption(key, defaultValue, prefix) {
149 | return getPreferences(prefix + '.' + key, defaultValue);
150 | }
151 |
152 | function getPreferences(key, defaultValue) {
153 | var userDefaults = NSUserDefaults.standardUserDefaults();
154 | if (!userDefaults.dictionaryForKey(pluginIdentifier)) {
155 | var defaultPreferences = NSMutableDictionary.alloc().init();
156 | userDefaults.setObject_forKey(defaultPreferences, pluginIdentifier);
157 | userDefaults.synchronize();
158 | }
159 | var value = userDefaults.dictionaryForKey(pluginIdentifier).objectForKey(key);
160 | return value === undefined ? defaultValue : value;
161 | }
162 |
163 | function setPreferences(key, value) {
164 | var userDefaults = NSUserDefaults.standardUserDefaults();
165 | var preferences;
166 | if (!userDefaults.dictionaryForKey(pluginIdentifier)) {
167 | preferences = NSMutableDictionary.alloc().init();
168 | } else {
169 | preferences = NSMutableDictionary.dictionaryWithDictionary(userDefaults.dictionaryForKey(pluginIdentifier));
170 | }
171 | preferences.setObject_forKey(value, key);
172 | userDefaults.setObject_forKey(preferences, pluginIdentifier);
173 | userDefaults.synchronize();
174 | }
175 |
176 | function parseHash(url) {
177 | url = url;
178 | var vars = {};
179 | var hashes = url.slice(url.indexOf('#') + 1).split('&');
180 | for(var i = 0; i < hashes.length; i++) {
181 | var hash = hashes[i].split('=');
182 | if(hash.length > 1) {
183 | vars[hash[0].toString()] = hash[1];
184 | } else {
185 | vars[hash[0].toString()] = null;
186 | }
187 | }
188 | return vars;
189 | }
--------------------------------------------------------------------------------