├── .appcast.xml
├── .gitignore
├── LICENSE
├── README.md
├── assets
└── smubar.png
├── chippen-charts.sketchplugin
└── Contents
│ ├── Resources
│ ├── .DS_Store
│ └── smubar.png
│ └── Sketch
│ ├── barchart.js
│ ├── barchart.js.map
│ ├── cliptexttosymbol.js
│ ├── cliptexttosymbol.js.map
│ ├── manifest.json
│ ├── nonrandom-barchart.js
│ ├── nonrandom-barchart.js.map
│ ├── randomfill.js
│ └── randomfill.js.map
├── images
├── 1_selectLayers.png
├── 2_random2.png
├── 3_randomResult.png
├── 4_trendUp2.png
├── 5_trendUpResult.png
├── 6_showcase.png
├── dialogs.png
├── header-original.gif
├── showcase-paste-clipboard-into-symbols.gif
├── showcase-paste-clipboard-into-symbols_640px.gif
├── showcase1-o.gif
├── showcase2-definedValues.gif
└── showcase_random-fill_chippencharts_sketch-plugin.gif
├── package-lock.json
├── package.json
└── src
├── barchart.js
├── cliptexttosymbol.js
├── manifest.json
├── nonrandom-barchart.js
├── randomfill.js
└── utils.js
/.appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 | -
8 |
9 |
10 | -
11 |
12 |
13 | -
14 |
15 |
16 | -
17 |
18 |
19 | -
20 |
21 |
22 | -
23 |
24 |
25 | -
26 |
27 |
28 | -
29 |
30 |
31 | -
32 |
33 |
34 | -
35 |
36 |
37 | -
38 |
39 |
40 | -
41 |
42 |
43 | -
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | node_modules
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Martin von Lupin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
Chippen charts
2 |
3 |
4 |
5 |
6 |
7 | Random bar charts for your data driven mockups
8 |
9 |
10 |
11 | This is a Sketch plugin for creating charts with random or user defined data for use in mockups. Change the size of selected rectangles. Chose between random and linear. Works for both horizontal and vertical bar charts.
12 | Furthermore, the latest feature allows you to paste text from the clipboard straight into symbol overrides. How good is that, heh?
13 |
14 | Made with love by [Small Multiples](https://smallmultiples.com.au/) in Chippendale, Sydney.
15 |
16 | **List of current features**
17 | - Bar chart with random values
18 | - Bar chart with actual data
19 | - Paste clipboard text into symbols
20 | - Apply random fill to selection **(new)**
21 |
22 |
23 | ## How to install
24 |
25 | 1. Click the `Clone or download` button in the top right and choose `Download Zip`
26 | 2. Save the ZIP file to your harddrive
27 | 3. Open the downloaded file and double click the sketch file `chippen-charts.sketchplugin`
28 | 4. The plugin is installed and you can use it via the menu `Plugins` > `Chippen charts`
29 |
30 |
31 | ## Features
32 |
33 | ### 1. Random bar chart from selected layers
34 |
35 | If you don't have data yet but still want to design a bar chart for your mockup, you can use the option to apply random values. You can also apply not-so-random values when choosing trend up or trend down.
36 |
37 |
38 |
39 | ---
40 |
41 | ### 2. Defined bar chart from selected layers
42 |
43 | If you have data that you want to apply to your chart this option is for you. You can even copy / paste from Excel columns or rows. How cool is that, right? In case your number values don't exactly match your desired pixel values, you have the option to apply a multiplier or set a maximum height. By default values don't get scaled.
44 |
45 |
46 |
47 | ---
48 |
49 | ### 3. Paste clipboard text into symbols
50 |
51 | Get your clipboard loaded with amazing text content, fire up the plugin, and let the magic of the plugin paste everything into your symbol override of choice. It's as simple as that.
52 |
53 | You might wonder why you wouldn't wanna use the Sketch Data feature for that. The thing is, the Sketch Data feature does not preserve the order of elements, which this plugin does.
54 |
55 |
56 |
57 | ### 4. Random fill
58 |
59 | Apply random colours to selected layers or choose to apply colours based on the order layers in order to create a gradient. All that needs to be done is choosing two hex colours and the number of colours you want to be generated.
60 |
61 |
62 |
63 | ---
64 |
65 |
66 | ## How the plugin works
67 |
68 | ### Dialog boxes for random and user defined action
69 |
70 | Those dialog boxes give you a good summary of what the plugin is capable of. Just have a look at the various input options.
71 |
72 |
73 |
74 | ### Workflow
75 | 1. **Create** desired amount of rectangles
76 | 2. Layers must be in the correct **order**
77 | 3. Make sure layers are either bottom or left **aligned**
78 | 4. **Run the plugin** and adjust _settings_ in dialog window if necessary
79 | 5. The size of you bars will be adjusted
80 |
81 | ### Settings
82 | #### Horizontal or vertical bar chart
83 | Chippen Chart detects wheter you are about to create a vertical or horizontal bar chart using the x and y-position of your selected layers. If there is no common x or y-value it will by default apply the logic for vertical bars.
84 |
85 | #### Min and max size (pixel)
86 | Chippen chart detects minimum and maximum pixel height of selected layers and apply those to the new bar chart. You can also adjust your desired extrema in the dialog window. If all selected layers share the same height the plugin will apply a default value for either min or max.
87 |
88 | #### Trend type
89 | You can choose between 5 trend types. All of them will use the min and max value you define. _Random_ will apply completely random integer numbers. Linear_ will interpolate values between min and max. _Natural_ will do the same while adding a notion of randomness.
90 |
91 | - [x] Random
92 | - [ ] Trend going up ↑ (linear)
93 | - [ ] Trend going up ↑ (natural)
94 | - [ ] Trend going down ↓ (linear)
95 | - [ ] Trend going down ↓ (natural)
96 |
97 | ### Examples
98 |
99 | #### Defining a chart with trend going up
100 | Besindes random numbers you can choose between linear trends and natural trends. Natural trends are like linear ones, but they have a little bit of randomeness aplpied to them.
101 |
102 |
103 | #### This is how a trend up (natural) chart looks like
104 |
105 |
106 | #### Showcase of different types
107 |
108 |
109 | ## Version history
110 |
111 | ##### 3.6.1
112 |
113 | - Random fill: add option to use layer order
114 |
115 | ##### 3.6
116 |
117 | - New feature: Random fill
118 | - Bar charts: Force vertical or horizontal bar chart type
119 | - Updates to popup
120 |
121 | ##### 3.5.4
122 |
123 | - Bugfix for wrong adjustment of bars when data point has value zero
124 |
125 | ##### 3.5.3
126 |
127 | - Add data value to layer name in the format "Layer name {:value:}"
128 | - Optimise workflow with negative values for both, random and user-defined charts
129 |
130 | ##### 3.5.2
131 |
132 | - Bug fix for "Defined bar chart from selected layers" where bars wouldn't reposition correctly when first value is negative.
133 | - Overall improvements in dealing with negative values.
134 |
135 | ##### 3.5.1
136 |
137 | - Bug fix for "Defined bar chart from selected layers" where the scale values from the input fields would not be used properly to calculate heights of bars
138 |
139 | ##### 3.5
140 |
141 | - Introducing new feature: Paste clipboard text into symbol overrides
142 |
143 | ##### 3.4
144 |
145 | - Introducing new feature: Create bar charts using user defined values
146 | - Enhancements to dialog design
147 |
148 | ##### 3.3.3
149 |
150 | - Fixing update issues
151 |
152 | ## Troubleshooting
153 | Unintended results will appear when the proportional resizing is set between a layer's width and height. **Proportional resizing must be disabled** 🔓
154 |
155 | ## Love it or hate it?
156 | Let us know. info@small.mu | @smallmultiples
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/assets/smubar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallmultiples/sketch-chippencharts/0cef328ad86b40f35a04776996acecb2c797dac8/assets/smubar.png
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Resources/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallmultiples/sketch-chippencharts/0cef328ad86b40f35a04776996acecb2c797dac8/chippen-charts.sketchplugin/Contents/Resources/.DS_Store
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Resources/smubar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/smallmultiples/sketch-chippencharts/0cef328ad86b40f35a04776996acecb2c797dac8/chippen-charts.sketchplugin/Contents/Resources/smubar.png
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Sketch/barchart.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/barchart.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/barchart.js":
95 | /*!*************************!*\
96 | !*** ./src/barchart.js ***!
97 | \*************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch */ "sketch");
104 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch__WEBPACK_IMPORTED_MODULE_0__);
105 | /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ "./src/utils.js");
106 |
107 | // documentation: https://developer.sketchapp.com/reference/api/
108 |
109 | /* harmony default export */ __webpack_exports__["default"] = (function () {
110 | log('~~ Run Chippen charts ~~');
111 | var doc = sketch__WEBPACK_IMPORTED_MODULE_0___default.a.getSelectedDocument();
112 | var selectedLayers = doc.selectedLayers;
113 | /*
114 | Analyse selected layers
115 | */
116 |
117 | var isVertical = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["isVerticalBarchart"])(doc.selectedLayers);
118 | var minMax_fromSelection = getMinMax(doc.selectedLayers, isVertical);
119 | /*
120 | User input
121 | */
122 |
123 | var response = myinput(minMax_fromSelection, doc.selectedLayers.layers.length, isVertical);
124 | var minMax = [response.min, response.max];
125 |
126 | if (response.code !== 1000) {
127 | return;
128 | }
129 |
130 | var myRandomSlots = [];
131 |
132 | if (response.trendTypeInput == 0) {
133 | // Only for random trend
134 | // Set 2 random bars to min and max
135 | myRandomSlots = twoRandomSlots(selectedLayers.layers.length, 'Random');
136 | } // Force other type than detected if user has selected force type
137 |
138 |
139 | if (response.forcetype) {
140 | isVertical = !isVertical;
141 | }
142 | /*
143 | UI message
144 | */
145 |
146 |
147 | var trendTypeInput_name = ["random data", "trend going up ↑ (linear)", "trend going up ↑ (natural)", "trend going down ↓ (linear)", "trend going down ↓ (natural)"];
148 | var isVertical_name = "vertical";
149 |
150 | if (!isVertical) {
151 | isVertical_name = "horizontal";
152 | }
153 |
154 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.message("".concat(doc.selectedLayers.length, " ").concat(isVertical_name, " bars with ").concat(trendTypeInput_name[response.trendTypeInput], " (").concat(minMax[0], "px\u2013").concat(minMax[1], "px)"));
155 | /*
156 | Changing size
157 | */
158 |
159 | var firstBarVal = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["getValFromLayerName"])(selectedLayers.layers[0].name);
160 | var baseLine = 0;
161 |
162 | if (isVertical) {
163 | baseLine = selectedLayers.layers[0].frame.y + selectedLayers.layers[0].frame.height; // Adjust when first value of existing bar is negative
164 | // Based on layer name
165 |
166 | if (firstBarVal < 0) {
167 | baseLine = baseLine - Math.abs(firstBarVal);
168 | }
169 |
170 | ;
171 | } else {
172 | if (firstBarVal >= 0) {
173 | baseLine = selectedLayers.layers[0].frame.x;
174 | } else if (firstBarVal < 0) {
175 | baseLine = selectedLayers.layers[0].frame.x + Math.abs(firstBarVal);
176 | }
177 | }
178 |
179 | for (var i = 0; i < selectedLayers.layers.length; i++) {
180 | var newLength = 1;
181 |
182 | if (response.trendTypeInput == 3 || response.trendTypeInput == 4) {
183 | // reverse minMax if trend is going down
184 | // and after that just use same code as for trend going up
185 | minMax = [minMax[1], minMax[0]];
186 | response.trendTypeInput = response.trendTypeInput - 2;
187 | } // Random
188 |
189 |
190 | if (response.trendTypeInput == 0) {
191 | // random values between min and max
192 | newLength = Math.floor(Math.random() * (minMax[1] - minMax[0])) + minMax[0];
193 |
194 | if (i == myRandomSlots[0]) {
195 | // force a random slot to be min
196 | newLength = minMax[0];
197 | }
198 |
199 | if (i == myRandomSlots[1]) {
200 | // force a random slot to be max
201 | newLength = minMax[1];
202 | }
203 | } // Trend going up
204 |
205 |
206 | if (response.trendTypeInput == 1 || response.trendTypeInput == 2) {
207 | var stepIncrease = (minMax[1] - minMax[0]) / selectedLayers.layers.length;
208 |
209 | if (response.trendTypeInput == 1) {
210 | newLength = stepIncrease * i + minMax[0];
211 | } else if (response.trendTypeInput == 2) {
212 | var increase_random = stepIncrease * Math.random();
213 | var plusOrMinus = Math.random() < 0.5 ? -1 : 1;
214 | newLength = stepIncrease * i + minMax[0] + increase_random * plusOrMinus;
215 | } // force first and last to be min and max
216 |
217 |
218 | if (i == 0) {
219 | newLength = minMax[0];
220 | } else if (i == selectedLayers.layers.length - 1) {
221 | newLength = minMax[1];
222 | }
223 |
224 | newLength = Math.round(newLength * 10) / 10;
225 | } // Length can't be zero
226 |
227 |
228 | if (newLength == 0) {
229 | newLength = 1;
230 | } // Change Width / Height
231 |
232 |
233 | if (isVertical) {
234 | // Change height
235 | selectedLayers.layers[i].frame.height = Math.abs(newLength); // Move to baseline
236 |
237 | if (newLength > 0) {
238 | // Reposition bars with positive values
239 | selectedLayers.layers[i].frame.y = baseLine - Math.abs(newLength);
240 | } else {
241 | // Reposition bars with negative values
242 | selectedLayers.layers[i].frame.y = baseLine;
243 | }
244 | } else {
245 | // Reset position, just in case
246 | selectedLayers.layers[i].frame.x = baseLine; // Change Width
247 |
248 | selectedLayers.layers[i].frame.width = Math.abs(newLength); // Reposition bars with negative values
249 |
250 | if (newLength < 0) {
251 | selectedLayers.layers[i].frame.x = selectedLayers.layers[i].frame.x - Math.abs(newLength);
252 | }
253 | } // Rename layer
254 | // Example: Rectangle ==> Rectangle {:12:}
255 |
256 |
257 | selectedLayers.layers[i].name = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["renameLayer"])(selectedLayers.layers[i].name, newLength);
258 | }
259 | });
260 |
261 | function getMinMax(arr, isVertical) {
262 | // arr needs to be doc.selectedLayers
263 | var min = 0;
264 | var max = 0;
265 |
266 | if (isVertical) {
267 | // Vertical bar chart (get minMax height)
268 | for (var i = 0; i < arr.layers.length; i++) {
269 | var thisHeight = arr.layers[i].frame.height; // Max
270 |
271 | if (thisHeight > max) {
272 | max = thisHeight;
273 | } // Min
274 |
275 |
276 | if (min == 0) {
277 | // set min at first runfirst
278 | min = max;
279 | }
280 |
281 | if (thisHeight < min) {
282 | min = thisHeight;
283 | }
284 | }
285 | } else {
286 | // Horizontal bar chart (get minMax width)
287 | for (var i = 0; i < arr.layers.length; i++) {
288 | var thisWidth = arr.layers[i].frame.width; // Max
289 |
290 | if (thisWidth > max) {
291 | max = thisWidth;
292 | } // Min
293 |
294 |
295 | if (min == 0) {
296 | // set min at first run
297 | min = max;
298 | }
299 |
300 | if (thisWidth < min) {
301 | min = thisWidth;
302 | }
303 | }
304 | }
305 |
306 | return [Math.ceil(min), Math.ceil(max)];
307 | }
308 |
309 | function twoRandomSlots(length, type) {
310 | var slotOne = 0;
311 | var slotTwo = 0;
312 |
313 | if (type == 'Random') {
314 | slotOne = Math.floor(Math.random() * length / 2);
315 | slotTwo = Math.floor(Math.random() * length / 2) + Math.floor(length / 2);
316 | }
317 |
318 | return [slotOne, slotTwo];
319 | }
320 |
321 | function myinput() {
322 | var myMinMax = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [20, 100];
323 | var numOfBars = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
324 | var my_isVertical = arguments.length > 2 ? arguments[2] : undefined;
325 | var myresponse = {};
326 |
327 | if (myMinMax.length != 2 || myMinMax[0] == myMinMax[1]) {
328 | if (myMinMax[0] > 100) {
329 | myMinMax = [20, myMinMax[1]];
330 | } else {
331 | myMinMax = [myMinMax[0], 100];
332 | }
333 | }
334 |
335 | if (numOfBars == 0) {
336 | myresponse.code == 1001;
337 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("Sorry buddy", "You need to select multiple rectangles (bars) for this plugin to work.");
338 | }
339 |
340 | if (numOfBars != 0) {
341 | if (numOfBars == 1) {
342 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("Hey, just letting you know", "Most awesome results come when selecting more than 1 bar.");
343 | } // Create initial view panel
344 |
345 |
346 | var width = 280;
347 | var height = 40;
348 | var view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, height)); // Min Max input
349 |
350 | var minInput = NSTextField.alloc().initWithFrame(NSMakeRect(0.0, 15.0, 130, 25.0));
351 | minInput.cell().setPlaceholderString(myMinMax[0] + " (min)");
352 | view.addSubview(minInput);
353 | var maxInput = NSTextField.alloc().initWithFrame(NSMakeRect(150, 15.0, 130, 25.0));
354 | maxInput.cell().setPlaceholderString(myMinMax[1] + " (max)");
355 | view.addSubview(maxInput); // Nature of data
356 |
357 | var trendTypeInput = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 135)); // Acts like a template (prototype) for our radio buttons
358 |
359 | var buttonFormat;
360 | buttonFormat = NSButtonCell.alloc().init();
361 | buttonFormat.setButtonType(NSRadioButton); // The matrix will contain all the cells (radio buttons)
362 |
363 | var matrixFormat = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(NSMakeRect(0, 0, 260, 135), // Horizontal position, vertical position, width, height
364 | NSRadioModeMatrix, // This makes the radio buttons work together
365 | buttonFormat, 5, // 1 row
366 | 1 // 3 columns (for 3 radio buttons)
367 | ); // Settings the size of the radio buttons
368 |
369 | matrixFormat.setCellSize(CGSizeMake(260, 25)); // Adding the radio buttons to the form
370 |
371 | var cells = matrixFormat.cells();
372 | cells.objectAtIndex(0).setTitle("Random");
373 | cells.objectAtIndex(1).setTitle("Trend going up ↑ (linear)");
374 | cells.objectAtIndex(2).setTitle("Trend going up ↑ (natural)");
375 | cells.objectAtIndex(3).setTitle("Trend going down ↓ (linear)");
376 | cells.objectAtIndex(4).setTitle("Trend going down ↓ (natural)"); // Adding the matrix to the form
377 |
378 | trendTypeInput.addSubview(matrixFormat); // Bar type: Vertical or horizontal
379 |
380 | var bartype_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Vertical or horizontal?", 12, true, NSMakeRect(0, 0, width, 16));
381 | var bartype_radio = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 48));
382 | var matrixFormat_bartype = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(NSMakeRect(0, 0, 260, 48), NSRadioModeMatrix, buttonFormat, 2, 1);
383 | matrixFormat_bartype.setCellSize(CGSizeMake(260, 25));
384 | var bartype_radio1_label = my_isVertical ? "Automatic (vertical detected)" : "Automatic (horizontal detected)";
385 | var bartype_radio2_label = my_isVertical ? "Force horizontal" : "Force vertical";
386 | var cells_bartype = matrixFormat_bartype.cells();
387 | cells_bartype.objectAtIndex(0).setTitle(bartype_radio1_label);
388 | cells_bartype.objectAtIndex(1).setTitle(bartype_radio2_label);
389 | bartype_radio.addSubview(matrixFormat_bartype); // Setup the window
390 |
391 | var alert = COSAlertWindow.new();
392 |
393 | if (numOfBars == 1) {
394 | alert.setMessageText("Create your random bar chart \nwith 1 selected layer");
395 | } else {
396 | alert.setMessageText("Create your random bar chart \nwith ".concat(numOfBars, " selected layers"));
397 | }
398 |
399 | alert.addButtonWithTitle("Run");
400 | alert.addButtonWithTitle("Cancel");
401 | alert.setInformativeText("This is for a bar chart where random values are applied \nto the layers of your selection.");
402 | var extrema_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Define extrema of bars", 12, true, NSMakeRect(0, 0, width, 16));
403 | alert.addAccessoryView(extrema_label); //alert.addTextLabelWithValue("Define extrema of bars");
404 |
405 | alert.addAccessoryView(view);
406 | var trend_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Specify the desired trend", 12, true, NSMakeRect(0, 0, width, 16));
407 | alert.addAccessoryView(trend_label); //alert.addTextLabelWithValue("Specify the desired trend");
408 |
409 | alert.addAccessoryView(trendTypeInput);
410 | alert.addAccessoryView(bartype_label);
411 | alert.addAccessoryView(bartype_radio);
412 | /*
413 | Key navigation (popup)
414 | */
415 |
416 | alert.alert().window().setInitialFirstResponder(minInput);
417 | minInput.setNextKeyView(maxInput);
418 | maxInput.setNextKeyView(minInput);
419 | /*
420 | Note
421 | */
422 |
423 | var note_line1 = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("\nPlease make sure proportional scaling is disabled", 11, false, NSMakeRect(0, 0, width, 16 * 2), 0.3);
424 | alert.addAccessoryView(note_line1);
425 | var responseCode = alert.runModal();
426 |
427 | if (responseCode == 1000) {
428 | myresponse.code = 1000; // OK
429 | // pass minmax input
430 |
431 | if (minInput.stringValue() == "") {
432 | myresponse.min = myMinMax[0];
433 | } else {
434 | myresponse.min = parseInt(minInput.stringValue());
435 | }
436 |
437 | if (maxInput.stringValue() == "") {
438 | myresponse.max = myMinMax[1];
439 | } else {
440 | myresponse.max = parseInt(maxInput.stringValue());
441 | } // Force bar chart type
442 |
443 |
444 | var forcetype_index = matrixFormat_bartype.cells().indexOfObject(matrixFormat_bartype.selectedCell());
445 | myresponse.forcetype = forcetype_index == 0 ? false : true;
446 | } else {
447 | // Cancel
448 | myresponse.code = 1001;
449 | }
450 |
451 | myresponse.trendTypeInput = matrixFormat.cells().indexOfObject(matrixFormat.selectedCell());
452 | }
453 |
454 | return myresponse;
455 | }
456 |
457 | /***/ }),
458 |
459 | /***/ "./src/utils.js":
460 | /*!**********************!*\
461 | !*** ./src/utils.js ***!
462 | \**********************/
463 | /*! exports provided: getSymbolInstances, onlyUnique, iterativeGapFilling, createLabel, createTextField, createDropdown, createCheckbox, getValFromLayerName, renameLayer, isVerticalBarchart, getBarHeight */
464 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
465 |
466 | "use strict";
467 | __webpack_require__.r(__webpack_exports__);
468 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSymbolInstances", function() { return getSymbolInstances; });
469 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onlyUnique", function() { return onlyUnique; });
470 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iterativeGapFilling", function() { return iterativeGapFilling; });
471 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLabel", function() { return createLabel; });
472 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextField", function() { return createTextField; });
473 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createDropdown", function() { return createDropdown; });
474 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createCheckbox", function() { return createCheckbox; });
475 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getValFromLayerName", function() { return getValFromLayerName; });
476 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renameLayer", function() { return renameLayer; });
477 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isVerticalBarchart", function() { return isVerticalBarchart; });
478 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBarHeight", function() { return getBarHeight; });
479 | function getSymbolInstances(source, symbolMaster) {
480 | // https://github.com/sonburn/
481 | var symbolInstances = NSMutableArray.array();
482 | source.sketchObject.pages().forEach(function (page) {
483 | var predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@', 'MSSymbolInstance', symbolMaster.sketchObject.objectID());
484 | page.children().filteredArrayUsingPredicate(predicate).forEach(function (instance) {
485 | return symbolInstances.addObject(instance);
486 | });
487 | });
488 | return symbolInstances;
489 | }
490 | function onlyUnique(value, index, self) {
491 | return self.indexOf(value) === index;
492 | }
493 | function iterativeGapFilling(array, length) {
494 | var newArray = [];
495 |
496 | for (var i = 0; i < length; i++) {
497 | var loop = Math.floor(i / array.length);
498 | var index = i - loop * array.length;
499 | newArray.push(array[index]);
500 | }
501 |
502 | return newArray;
503 | }
504 | /**********************/
505 |
506 | /* POPUP */
507 |
508 | /**********************/
509 |
510 | /*
511 | Utils from Marc Bouchenoire
512 | for easier UI design
513 | https://github.com/bouchenoiremarc
514 | */
515 |
516 | function createLabel(text, fontSize, bold, frame, opacity) {
517 | var label = NSTextField.alloc().initWithFrame(frame);
518 | label.setStringValue(text);
519 | label.setFont(bold ? NSFont.boldSystemFontOfSize(fontSize) : NSFont.systemFontOfSize(fontSize));
520 | label.setBezeled(false);
521 | label.setDrawsBackground(false);
522 | label.setEditable(false);
523 | label.setSelectable(false);
524 | if (opacity) label.setAlphaValue(opacity);
525 | return label;
526 | }
527 | function createTextField(value, placeholder, frame) {
528 | var textfield = NSTextField.alloc().initWithFrame(frame);
529 | textfield.cell().setWraps(false);
530 | textfield.cell().setScrollable(true);
531 | textfield.setStringValue(value);
532 | if (placeholder) textfield.setPlaceholderString(placeholder);
533 | return textfield;
534 | }
535 | function createDropdown(values, frame) {
536 | var dropdown = NSPopUpButton.alloc().initWithFrame(frame);
537 | dropdown.addItemsWithTitles(values);
538 | return dropdown;
539 | }
540 | function createCheckbox(text, checked, frame) {
541 | checked = checked == false ? NSOffState : NSOnState;
542 | var checkbox = NSButton.alloc().initWithFrame(frame);
543 | checkbox.setButtonType(NSSwitchButton);
544 | checkbox.setBezelStyle(0);
545 | checkbox.setTitle(text);
546 | checkbox.setState(checked);
547 | return checkbox;
548 | }
549 | /**********************/
550 |
551 | /* VAL IN LAYER NAME */
552 |
553 | /**********************/
554 |
555 | function getValFromLayerName(name) {
556 | var a = name.split("{:");
557 |
558 | if (a.length == 1) {
559 | return false;
560 | }
561 |
562 | var b = a[1].split(":}");
563 | var val = parseFloat(b[0]);
564 |
565 | if (isNaN(val)) {
566 | return false;
567 | }
568 |
569 | return val;
570 | }
571 | function renameLayer(name, newVal) {
572 | var a = name.split("{:");
573 | var newName = name + " {:" + newVal + ":}";
574 |
575 | if (a.length > 1) {
576 | var b = a[1].split(":}");
577 |
578 | if (b.length == 1) {
579 | return newName;
580 | }
581 |
582 | var newName = a[0] + "{:" + newVal + ":}" + b[1];
583 | }
584 |
585 | return newName;
586 | }
587 | /**********************/
588 |
589 | /* BARCHART */
590 |
591 | /**********************/
592 |
593 | function isVerticalBarchart(arr) {
594 | // arr needs to be doc.selectedLayers
595 | var isVertical = true;
596 |
597 | if (arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y) {
598 | // It's horizontal if
599 | // 1. First two bars share same x value (works for positive values)
600 | if (arr.layers[0].frame.x == arr.layers[1].frame.x) {
601 | isVertical = false;
602 | } // 2. Same y-baseline (works if first value is negative)
603 | // and they share same height
604 | // ! Needs check if first / second val is negative
605 | else if (arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
606 | isVertical = false;
607 | } else if (arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
608 | isVertical = false;
609 | }
610 | }
611 |
612 | return isVertical;
613 | }
614 | /**********************/
615 |
616 | /* NON-RANDO BARCHART */
617 |
618 | /**********************/
619 |
620 | function getBarHeight(arr, isVertical) {
621 | // arr needs to be doc.selectedLayers
622 | var barLength_str = "";
623 |
624 | for (var i = 0; i < arr.layers.length; i++) {
625 | var thisLength = undefined;
626 |
627 | if (isVertical) {
628 | thisLength = arr.layers[i].frame.height.toFixed(2); // reduce to 2 decimals
629 | } else {
630 | thisLength = arr.layers[i].frame.width.toFixed(2); // reduce to 2 decimals
631 | }
632 |
633 | thisLength = parseFloat(thisLength); // to remove decimals from integers
634 |
635 | if (i == 0) {
636 | barLength_str = "" + thisLength;
637 | } else {
638 | barLength_str = barLength_str + "," + thisLength;
639 | }
640 | }
641 |
642 | return barLength_str;
643 | }
644 |
645 | /***/ }),
646 |
647 | /***/ "sketch":
648 | /*!*************************!*\
649 | !*** external "sketch" ***!
650 | \*************************/
651 | /*! no static exports found */
652 | /***/ (function(module, exports) {
653 |
654 | module.exports = require("sketch");
655 |
656 | /***/ })
657 |
658 | /******/ });
659 | if (key === 'default' && typeof exports === 'function') {
660 | exports(context);
661 | } else {
662 | exports[key](context);
663 | }
664 | }
665 | that['onRun'] = __skpm_run.bind(this, 'default')
666 |
667 | //# sourceMappingURL=barchart.js.map
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Sketch/cliptexttosymbol.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/cliptexttosymbol.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/cliptexttosymbol.js":
95 | /*!*********************************!*\
96 | !*** ./src/cliptexttosymbol.js ***!
97 | \*********************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch */ "sketch");
104 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch__WEBPACK_IMPORTED_MODULE_0__);
105 | /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ "./src/utils.js");
106 |
107 | // documentation: https://developer.sketchapp.com/reference/api/
108 | // https://github.com/sonburn/symbol-instance-locator/blob/master/Symbol%20Instance%20Locator.sketchplugin/Contents/Sketch/script.js
109 |
110 | var symbolOverrideLayers;
111 | /* harmony default export */ __webpack_exports__["default"] = (function () {
112 | log('~~ Run Chippen charts ~~');
113 | var doc = sketch__WEBPACK_IMPORTED_MODULE_0___default.a.getSelectedDocument();
114 | var selectedLayers = doc.selectedLayers;
115 |
116 | var pluginName = __command.pluginBundle().name();
117 |
118 | if (selectedLayers.layers.length == 0) {
119 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert(pluginName, 'Please select at least 1 layer that contains a symbol override.');
120 | return false;
121 | }
122 | /*
123 | CLIPBOARD
124 | */
125 |
126 |
127 | var newLineSeparator = "\n";
128 | var sep = newLineSeparator;
129 | var pasteBoard = NSPasteboard.generalPasteboard(); // Turn a data in the string type
130 |
131 | var stringFromPasteBoard = pasteBoard.stringForType(NSPasteboardTypeString);
132 |
133 | if (stringFromPasteBoard == null) {
134 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert(pluginName, 'Your clipboard does not seem to be just text. Try again with only lines of text.');
135 | return false;
136 | }
137 |
138 | var pasteboardLines = stringFromPasteBoard.split(newLineSeparator);
139 | /*
140 | SELECTED SYMBOLS
141 | */
142 |
143 | var selectedSymbols = selectedLayers.layers.filter(function (layer) {
144 | return layer.type == "SymbolInstance" || layer.type == "SymbolMaster";
145 | });
146 |
147 | if (selectedSymbols.length == 0) {
148 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert(pluginName, 'Please select at least 1 layer that contains a symbol.');
149 | return false;
150 | }
151 |
152 | var symbolsWithOverrides = selectedSymbols.filter(function (symbol) {
153 | return symbol.overrides.length != 0;
154 | });
155 |
156 | if (symbolsWithOverrides.length == 0) {
157 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert(pluginName, 'Please select at least 1 symbol that contains a text override.');
158 | return false;
159 | }
160 |
161 | var symbolsIDs = symbolsWithOverrides.map(function (symbol) {
162 | return symbol.symbolId;
163 | });
164 | var uniqueSymbolIDs = symbolsIDs.filter(_utils_js__WEBPACK_IMPORTED_MODULE_1__["onlyUnique"]);
165 |
166 | if (uniqueSymbolIDs.length > 1) {
167 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert(pluginName, "Please use only symbols of the same kind. Maybe you want to try to use only symbols like \"".concat(symbolsWithOverrides[0].name, "\"."));
168 | return false;
169 | }
170 | /*
171 | Informative Text
172 | */
173 |
174 |
175 | var warningMsg = "";
176 |
177 | if (pasteboardLines.length > symbolsWithOverrides.length) {
178 | warningMsg = "There are more lines of text in the clipboard (".concat(pasteboardLines.length, ") than there are symbols in the selection (").concat(symbolsWithOverrides.length, "). That means not all content from clipboard will be used.");
179 | } else if (symbolsWithOverrides.length > pasteboardLines.length) {
180 | warningMsg = "There are more symbols selected (".concat(symbolsWithOverrides.length, ") than there are lines of text in the clipboard (").concat(pasteboardLines.length, "). Clipboard text will be repeated in the overflow symbols.");
181 | }
182 |
183 | var informativeText = "";
184 |
185 | if (warningMsg != "") {
186 | informativeText = "⚠️ Watch out! - " + warningMsg + " \n\nYou can go ahead but outcomes might not be as expected.";
187 | } else {
188 | informativeText = "You are about to alter ".concat(symbolsWithOverrides.length, " symbol overrides using text from the clipboard.");
189 | }
190 | /*
191 | Dropdown options
192 | */
193 |
194 |
195 | var stringvalueOverrides = symbolsWithOverrides[0].overrides.filter(function (override) {
196 | return override.property == 'stringValue';
197 | });
198 | var overrideOptions = stringvalueOverrides.map(function (override, index) {
199 | return "Override " + (parseInt(index) + 1) + " (" + override.value + ")";
200 | });
201 | /*
202 | Setup the window
203 | */
204 |
205 | var alert = COSAlertWindow.new();
206 | alert.setMessageText("Paste clipboard text into symbol overrides");
207 | alert.addButtonWithTitle("Run");
208 | alert.addButtonWithTitle("Cancel");
209 | alert.setInformativeText(informativeText);
210 | /*
211 | Input
212 | */
213 | // OVERRIDE DROPDOWN
214 |
215 | var alert_width = 280;
216 | var overrideOptions_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("What override shall it be? ", 12, true, NSMakeRect(0, 0, alert_width, 16));
217 | var overrideOptions_dropdown = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createDropdown"])(overrideOptions, NSMakeRect(-2, -1, 280, 24));
218 |
219 | if (overrideOptions.length > 1) {
220 | alert.addAccessoryView(overrideOptions_label);
221 | alert.addAccessoryView(overrideOptions_dropdown);
222 | } // REVERSE CHECKBOX
223 |
224 |
225 | var reverse_checkbox = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createCheckbox"])("Reverse order of clipboard text", false, NSMakeRect(-2, -1, 280, 24));
226 |
227 | if (pasteboardLines.length > 1) {
228 | alert.addAccessoryView(reverse_checkbox);
229 | }
230 | /*
231 | Response
232 | */
233 |
234 |
235 | var overrideIndex;
236 | var responseCode = alert.runModal();
237 |
238 | if (responseCode == 1000) {
239 | // Dropdown input
240 | var dropddownIndex = overrideOptions_dropdown.indexOfSelectedItem();
241 | var overrideID = stringvalueOverrides[dropddownIndex].id; // Mapping index of dropdown to index of overrides.
242 | // Dropdown does only include stringValue overrides
243 | // and no symbolID overrides (top level of nested symbol).
244 | // That's why the length can differ.
245 |
246 | for (var i = 0; i < symbolsWithOverrides[0].overrides.length; i++) {
247 | if (symbolsWithOverrides[0].overrides[i].id == overrideID) {
248 | overrideIndex = i;
249 | }
250 | } // Checkbox input
251 |
252 |
253 | var reverse = false;
254 |
255 | if (Number(reverse_checkbox.state()) == 1) {
256 | reverse = true;
257 | }
258 | } else {
259 | // 1001
260 | return false;
261 | }
262 | /*
263 | OVERRIDE
264 | */
265 |
266 |
267 | var clip = pasteboardLines;
268 |
269 | if (reverse) {
270 | clip.reverse();
271 | }
272 |
273 | if (symbolsWithOverrides.length > clip.length) {
274 | var clip_filled = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["iterativeGapFilling"])(clip, symbolsWithOverrides.length);
275 | clip = clip_filled;
276 | }
277 |
278 | for (var i = 0; i < symbolsWithOverrides.length; i++) {
279 | symbolsWithOverrides[i].overrides[overrideIndex].value = clip[i];
280 | }
281 |
282 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.message("Text from clipboard was pasted into ".concat(symbolsWithOverrides.length, " symbols"));
283 | });
284 |
285 | /***/ }),
286 |
287 | /***/ "./src/utils.js":
288 | /*!**********************!*\
289 | !*** ./src/utils.js ***!
290 | \**********************/
291 | /*! exports provided: getSymbolInstances, onlyUnique, iterativeGapFilling, createLabel, createTextField, createDropdown, createCheckbox, getValFromLayerName, renameLayer, isVerticalBarchart, getBarHeight */
292 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
293 |
294 | "use strict";
295 | __webpack_require__.r(__webpack_exports__);
296 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSymbolInstances", function() { return getSymbolInstances; });
297 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onlyUnique", function() { return onlyUnique; });
298 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iterativeGapFilling", function() { return iterativeGapFilling; });
299 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLabel", function() { return createLabel; });
300 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextField", function() { return createTextField; });
301 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createDropdown", function() { return createDropdown; });
302 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createCheckbox", function() { return createCheckbox; });
303 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getValFromLayerName", function() { return getValFromLayerName; });
304 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renameLayer", function() { return renameLayer; });
305 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isVerticalBarchart", function() { return isVerticalBarchart; });
306 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBarHeight", function() { return getBarHeight; });
307 | function getSymbolInstances(source, symbolMaster) {
308 | // https://github.com/sonburn/
309 | var symbolInstances = NSMutableArray.array();
310 | source.sketchObject.pages().forEach(function (page) {
311 | var predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@', 'MSSymbolInstance', symbolMaster.sketchObject.objectID());
312 | page.children().filteredArrayUsingPredicate(predicate).forEach(function (instance) {
313 | return symbolInstances.addObject(instance);
314 | });
315 | });
316 | return symbolInstances;
317 | }
318 | function onlyUnique(value, index, self) {
319 | return self.indexOf(value) === index;
320 | }
321 | function iterativeGapFilling(array, length) {
322 | var newArray = [];
323 |
324 | for (var i = 0; i < length; i++) {
325 | var loop = Math.floor(i / array.length);
326 | var index = i - loop * array.length;
327 | newArray.push(array[index]);
328 | }
329 |
330 | return newArray;
331 | }
332 | /**********************/
333 |
334 | /* POPUP */
335 |
336 | /**********************/
337 |
338 | /*
339 | Utils from Marc Bouchenoire
340 | for easier UI design
341 | https://github.com/bouchenoiremarc
342 | */
343 |
344 | function createLabel(text, fontSize, bold, frame, opacity) {
345 | var label = NSTextField.alloc().initWithFrame(frame);
346 | label.setStringValue(text);
347 | label.setFont(bold ? NSFont.boldSystemFontOfSize(fontSize) : NSFont.systemFontOfSize(fontSize));
348 | label.setBezeled(false);
349 | label.setDrawsBackground(false);
350 | label.setEditable(false);
351 | label.setSelectable(false);
352 | if (opacity) label.setAlphaValue(opacity);
353 | return label;
354 | }
355 | function createTextField(value, placeholder, frame) {
356 | var textfield = NSTextField.alloc().initWithFrame(frame);
357 | textfield.cell().setWraps(false);
358 | textfield.cell().setScrollable(true);
359 | textfield.setStringValue(value);
360 | if (placeholder) textfield.setPlaceholderString(placeholder);
361 | return textfield;
362 | }
363 | function createDropdown(values, frame) {
364 | var dropdown = NSPopUpButton.alloc().initWithFrame(frame);
365 | dropdown.addItemsWithTitles(values);
366 | return dropdown;
367 | }
368 | function createCheckbox(text, checked, frame) {
369 | checked = checked == false ? NSOffState : NSOnState;
370 | var checkbox = NSButton.alloc().initWithFrame(frame);
371 | checkbox.setButtonType(NSSwitchButton);
372 | checkbox.setBezelStyle(0);
373 | checkbox.setTitle(text);
374 | checkbox.setState(checked);
375 | return checkbox;
376 | }
377 | /**********************/
378 |
379 | /* VAL IN LAYER NAME */
380 |
381 | /**********************/
382 |
383 | function getValFromLayerName(name) {
384 | var a = name.split("{:");
385 |
386 | if (a.length == 1) {
387 | return false;
388 | }
389 |
390 | var b = a[1].split(":}");
391 | var val = parseFloat(b[0]);
392 |
393 | if (isNaN(val)) {
394 | return false;
395 | }
396 |
397 | return val;
398 | }
399 | function renameLayer(name, newVal) {
400 | var a = name.split("{:");
401 | var newName = name + " {:" + newVal + ":}";
402 |
403 | if (a.length > 1) {
404 | var b = a[1].split(":}");
405 |
406 | if (b.length == 1) {
407 | return newName;
408 | }
409 |
410 | var newName = a[0] + "{:" + newVal + ":}" + b[1];
411 | }
412 |
413 | return newName;
414 | }
415 | /**********************/
416 |
417 | /* BARCHART */
418 |
419 | /**********************/
420 |
421 | function isVerticalBarchart(arr) {
422 | // arr needs to be doc.selectedLayers
423 | var isVertical = true;
424 |
425 | if (arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y) {
426 | // It's horizontal if
427 | // 1. First two bars share same x value (works for positive values)
428 | if (arr.layers[0].frame.x == arr.layers[1].frame.x) {
429 | isVertical = false;
430 | } // 2. Same y-baseline (works if first value is negative)
431 | // and they share same height
432 | // ! Needs check if first / second val is negative
433 | else if (arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
434 | isVertical = false;
435 | } else if (arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
436 | isVertical = false;
437 | }
438 | }
439 |
440 | return isVertical;
441 | }
442 | /**********************/
443 |
444 | /* NON-RANDO BARCHART */
445 |
446 | /**********************/
447 |
448 | function getBarHeight(arr, isVertical) {
449 | // arr needs to be doc.selectedLayers
450 | var barLength_str = "";
451 |
452 | for (var i = 0; i < arr.layers.length; i++) {
453 | var thisLength = undefined;
454 |
455 | if (isVertical) {
456 | thisLength = arr.layers[i].frame.height.toFixed(2); // reduce to 2 decimals
457 | } else {
458 | thisLength = arr.layers[i].frame.width.toFixed(2); // reduce to 2 decimals
459 | }
460 |
461 | thisLength = parseFloat(thisLength); // to remove decimals from integers
462 |
463 | if (i == 0) {
464 | barLength_str = "" + thisLength;
465 | } else {
466 | barLength_str = barLength_str + "," + thisLength;
467 | }
468 | }
469 |
470 | return barLength_str;
471 | }
472 |
473 | /***/ }),
474 |
475 | /***/ "sketch":
476 | /*!*************************!*\
477 | !*** external "sketch" ***!
478 | \*************************/
479 | /*! no static exports found */
480 | /***/ (function(module, exports) {
481 |
482 | module.exports = require("sketch");
483 |
484 | /***/ })
485 |
486 | /******/ });
487 | if (key === 'default' && typeof exports === 'function') {
488 | exports(context);
489 | } else {
490 | exports[key](context);
491 | }
492 | }
493 | that['onRun'] = __skpm_run.bind(this, 'default')
494 |
495 | //# sourceMappingURL=cliptexttosymbol.js.map
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Sketch/cliptexttosymbol.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/cliptexttosymbol.js","webpack://exports/./src/utils.js","webpack://exports/external \"sketch\""],"names":["symbolOverrideLayers","log","doc","sketch","getSelectedDocument","selectedLayers","pluginName","__command","pluginBundle","name","layers","length","UI","alert","newLineSeparator","sep","pasteBoard","NSPasteboard","generalPasteboard","stringFromPasteBoard","stringForType","NSPasteboardTypeString","pasteboardLines","split","selectedSymbols","filter","layer","type","symbolsWithOverrides","symbol","overrides","symbolsIDs","map","symbolId","uniqueSymbolIDs","onlyUnique","warningMsg","informativeText","stringvalueOverrides","override","property","overrideOptions","index","parseInt","value","COSAlertWindow","new","setMessageText","addButtonWithTitle","setInformativeText","alert_width","overrideOptions_label","createLabel","NSMakeRect","overrideOptions_dropdown","createDropdown","addAccessoryView","reverse_checkbox","createCheckbox","overrideIndex","responseCode","runModal","dropddownIndex","indexOfSelectedItem","overrideID","id","i","reverse","Number","state","clip","clip_filled","iterativeGapFilling","message","getSymbolInstances","source","symbolMaster","symbolInstances","NSMutableArray","array","sketchObject","pages","forEach","page","predicate","NSPredicate","predicateWithFormat","objectID","children","filteredArrayUsingPredicate","instance","addObject","self","indexOf","newArray","loop","Math","floor","push","text","fontSize","bold","frame","opacity","label","NSTextField","alloc","initWithFrame","setStringValue","setFont","NSFont","boldSystemFontOfSize","systemFontOfSize","setBezeled","setDrawsBackground","setEditable","setSelectable","setAlphaValue","createTextField","placeholder","textfield","cell","setWraps","setScrollable","setPlaceholderString","values","dropdown","NSPopUpButton","addItemsWithTitles","checked","NSOffState","NSOnState","checkbox","NSButton","setButtonType","NSSwitchButton","setBezelStyle","setTitle","setState","getValFromLayerName","a","b","val","parseFloat","isNaN","renameLayer","newVal","newName","isVerticalBarchart","arr","isVertical","y","x","width","height","getBarHeight","barLength_str","thisLength","undefined","toFixed"],"mappings":"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","file":"cliptexttosymbol.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/cliptexttosymbol.js\");\n","import sketch from 'sketch'\nimport { onlyUnique, iterativeGapFilling, createLabel, createDropdown, createCheckbox } from \"./utils.js\";\n// documentation: https://developer.sketchapp.com/reference/api/\n// https://github.com/sonburn/symbol-instance-locator/blob/master/Symbol%20Instance%20Locator.sketchplugin/Contents/Sketch/script.js\n\nvar symbolOverrideLayers;\n\nexport default function() {\n\tlog('~~ Run Chippen charts ~~')\n\n\tconst doc = sketch.getSelectedDocument()\n\tconst selectedLayers = doc.selectedLayers\n\n\tvar pluginName = __command.pluginBundle().name();\n\n\tif(selectedLayers.layers.length == 0) {\n\t\tsketch.UI.alert(pluginName,'Please select at least 1 layer that contains a symbol override.');\n\n\t\treturn false;\n\t}\n\t\t\n\t\n\t/*\n\t\tCLIPBOARD\n\t*/\n\n\tvar newLineSeparator = \"\\n\";\n\tvar sep = newLineSeparator;\n\n\tvar pasteBoard = NSPasteboard.generalPasteboard();\n // Turn a data in the string type\n var stringFromPasteBoard = pasteBoard.stringForType(NSPasteboardTypeString);\n\n if(stringFromPasteBoard == null){\n \tsketch.UI.alert(pluginName,'Your clipboard does not seem to be just text. Try again with only lines of text.');\n \treturn false;\n }\n\n var pasteboardLines = stringFromPasteBoard.split(newLineSeparator)\n \n\n\t/*\n\t\tSELECTED SYMBOLS\n\t*/\n\n\tconst selectedSymbols = selectedLayers.layers.filter(layer => layer.type == \"SymbolInstance\" || layer.type == \"SymbolMaster\")\n\tif (selectedSymbols.length == 0) {\n\t\tsketch.UI.alert(pluginName,'Please select at least 1 layer that contains a symbol.');\n\t\treturn false;\n\t}\n\t\n\tconst symbolsWithOverrides = selectedSymbols.filter(symbol => symbol.overrides.length != 0)\n\tif (symbolsWithOverrides.length == 0) {\n\t\tsketch.UI.alert(pluginName,'Please select at least 1 symbol that contains a text override.');\n\t\treturn false;\n\t}\n\n\tconst symbolsIDs = symbolsWithOverrides.map(symbol => {\n\t\treturn symbol.symbolId\n\t})\n\n\tconst uniqueSymbolIDs = symbolsIDs.filter( onlyUnique ); \n\t\n\tif(uniqueSymbolIDs.length > 1){\n\t\tsketch.UI.alert(pluginName,`Please use only symbols of the same kind. Maybe you want to try to use only symbols like \"${symbolsWithOverrides[0].name}\".`);\n\t\treturn false;\n\t}\n\n\n\t/*\n\t\tInformative Text\n\t*/\n\n\tvar warningMsg = \"\"\n\tif(pasteboardLines.length > symbolsWithOverrides.length){\n\t\twarningMsg = `There are more lines of text in the clipboard (${pasteboardLines.length}) than there are symbols in the selection (${symbolsWithOverrides.length}). That means not all content from clipboard will be used.`\n\t}else if(symbolsWithOverrides.length > pasteboardLines.length){\n\t\twarningMsg = `There are more symbols selected (${symbolsWithOverrides.length}) than there are lines of text in the clipboard (${pasteboardLines.length}). Clipboard text will be repeated in the overflow symbols.`\n\t}\n\n\tvar informativeText = \"\"\n\tif(warningMsg != \"\"){\n\t\tinformativeText = \"⚠️ Watch out! - \" + warningMsg + \" \\n\\nYou can go ahead but outcomes might not be as expected.\"\n\t}else{\n\t\tinformativeText = `You are about to alter ${symbolsWithOverrides.length} symbol overrides using text from the clipboard.`\n\t}\n\n\n\t/*\n\t\tDropdown options\n\t*/\n\n\tconst stringvalueOverrides = symbolsWithOverrides[0].overrides.filter(override => override.property == 'stringValue')\n\t\n\tconst overrideOptions = stringvalueOverrides.map((override, index) => {\n\t\treturn \"Override \" + (parseInt(index)+1) + \" (\" + override.value + \")\"\n\t})\n\t\n\n\t/*\n\t\tSetup the window\n \t*/\n\t\n\tvar alert = COSAlertWindow.new()\n\talert.setMessageText(\"Paste clipboard text into symbol overrides\")\n\talert.addButtonWithTitle(\"Run\")\n\talert.addButtonWithTitle(\"Cancel\")\n\talert.setInformativeText(informativeText)\n\t\n\n\t/*\n\t\tInput\n \t*/\n\n \t// OVERRIDE DROPDOWN\n \tvar alert_width = 280;\n\tvar overrideOptions_label = createLabel(\"What override shall it be? \", 12, true, NSMakeRect(0, 0, alert_width, 16));\n \tvar overrideOptions_dropdown = createDropdown(overrideOptions, NSMakeRect(-2, -1, 280, 24));\n\n \tif(overrideOptions.length>1){\n \t\talert.addAccessoryView(overrideOptions_label);\n \t\talert.addAccessoryView(overrideOptions_dropdown);\t\n \t}\n\n \t// REVERSE CHECKBOX\n \tvar reverse_checkbox = createCheckbox(\"Reverse order of clipboard text\", false, NSMakeRect(-2, -1, 280, 24));\n \t\n \tif(pasteboardLines.length>1){\n \t\talert.addAccessoryView(reverse_checkbox);\n \t}\n \n\n \t/*\n\t\tResponse\n\t*/\n\n\tvar overrideIndex;\n\tvar responseCode = alert.runModal();\n\t\n\tif(responseCode == 1000){\n\t\t// Dropdown input\n\t\tvar dropddownIndex = overrideOptions_dropdown.indexOfSelectedItem();\n\t\tvar overrideID = stringvalueOverrides[dropddownIndex].id;\n\n\t\t// Mapping index of dropdown to index of overrides.\n\t\t// Dropdown does only include stringValue overrides\n\t\t// and no symbolID overrides (top level of nested symbol).\n\t\t// That's why the length can differ.\n\t\tfor(var i=0; i clip.length){\n\t\tvar clip_filled = iterativeGapFilling(clip, symbolsWithOverrides.length)\n\t\tclip = clip_filled;\n\t}\n\n\tfor(var i=0; i symbolInstances.addObject(instance));\n\t});\n\n\treturn symbolInstances;\n}\n\nexport function onlyUnique(value, index, self) { \n return self.indexOf(value) === index;\n}\n\nexport function iterativeGapFilling(array, length){\n\tvar newArray = [];\n\tfor(var i=0; i 1){\n\t\tvar b = a[1].split(\":}\");\n\t\tif(b.length == 1){return newName;}\n\t\tvar newName = a[0] + \"{:\" + newVal + \":}\" + b[1];\n\t}\n\n\treturn newName\n}\n\n\n/**********************/\n/* BARCHART */\n/**********************/\n\nexport function isVerticalBarchart(arr){\n\t// arr needs to be doc.selectedLayers\n\tvar isVertical = true\n\tif(arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y){\n\t\t// It's horizontal if\n\t\t// 1. First two bars share same x value (works for positive values)\n\t\tif(arr.layers[0].frame.x == arr.layers[1].frame.x){\n\t\t\tisVertical = false;\n\t\t}\n\t\t// 2. Same y-baseline (works if first value is negative) \n\t\t// and they share same height\n\t\t// ! Needs check if first / second val is negative\n\t\telse if(arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){\n\t\t\tisVertical = false;\t\n\t\t}\n\t\telse if(arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){\n\t\t\tisVertical = false;\t\n\t\t}\n\t}\n\treturn isVertical\n}\n\n\n/**********************/\n/* NON-RANDO BARCHART */\n/**********************/\n\nexport function getBarHeight(arr, isVertical){\n\t// arr needs to be doc.selectedLayers\n\tvar barLength_str = \"\"\n\t\n\tfor(var i=0; i= 0) {
177 | baseLine = selectedLayers.layers[0].frame.x;
178 | } else if (firstBarVal < 0) {
179 | baseLine = selectedLayers.layers[0].frame.x + Math.abs(firstBarVal);
180 | }
181 | }
182 |
183 | for (var i = 0; i < selectedLayers.layers.length; i++) {
184 | var newLength = 1;
185 |
186 | if (response.numbers[i] == undefined) {
187 | newLength = undefined; // no bar will be changed and no error will be thrown (it's undefined by default anyway)
188 | } else {
189 | if (response.scaleType == 1) {
190 | // Multiplier
191 | newLength = response.numbers[i] * response.scaleValue;
192 | } else if (response.scaleType == 2) {
193 | // Set max height
194 | newLength = response.numbers[i] * response.scaleValue / response.max;
195 | } else {
196 | // none
197 | newLength = response.numbers[i];
198 | }
199 | } // Length can't be zero
200 |
201 |
202 | if (newLength == 0) {
203 | newLength = 0.5;
204 | response.numbers[i] = 0.5;
205 | } // Change Width / Height
206 |
207 |
208 | if (isVertical) {
209 | // Change height
210 | selectedLayers.layers[i].frame.height = Math.abs(newLength); // Move to baseline
211 |
212 | if (newLength > 0) {
213 | // Reposition bars with positive values
214 | selectedLayers.layers[i].frame.y = baseLine - Math.abs(newLength);
215 | } else {
216 | // Reposition bars with negative values
217 | selectedLayers.layers[i].frame.y = baseLine;
218 | }
219 | } else {
220 | // Reset position, just in case
221 | selectedLayers.layers[i].frame.x = baseLine; // Change width
222 |
223 | selectedLayers.layers[i].frame.width = Math.abs(newLength); // Reposition bars with negative values
224 |
225 | if (newLength < 0) {
226 | selectedLayers.layers[i].frame.x = selectedLayers.layers[i].frame.x - Math.abs(newLength);
227 | }
228 | } // Rename layer
229 | // Data value will be added to layer name
230 | // Example: Rectangle ==> Rectangle {:12:}
231 |
232 |
233 | selectedLayers.layers[i].name = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["renameLayer"])(selectedLayers.layers[i].name, response.numbers[i]);
234 | } // Notification
235 | // Alert in case number of selected layers
236 | // does not match amount of numbers
237 |
238 |
239 | if (alert_diff != 0) {
240 | if (alert_diff > 0) {
241 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("\uD83D\uDE07 Just letting you know", "Only the first ".concat(response.numbers.length, " of your selected layer(s) have been adjusted. There weren't enough number values to adjust the last ").concat(Math.abs(alert_diff), " layer(s). Maybe check the separator options (comma, etc)."));
242 | } else if (alert_diff < 0) {
243 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("\uD83D\uDE07 Just letting you know", "The last ".concat(Math.abs(alert_diff), " values weren't used as there weren't enough layer(s) selected."));
244 | }
245 | }
246 | });
247 |
248 | function getMinMax(arr, isVertical) {
249 | // arr needs to be doc.selectedLayers
250 | var min = 0;
251 | var max = 0;
252 |
253 | if (isVertical) {
254 | // Vertical bar chart (get minMax height)
255 | for (var i = 0; i < arr.layers.length; i++) {
256 | var thisHeight = arr.layers[i].frame.height; // Max
257 |
258 | if (thisHeight > max) {
259 | max = thisHeight;
260 | } // Min
261 |
262 |
263 | if (min == 0) {
264 | // set min at first runfirst
265 | min = max;
266 | }
267 |
268 | if (thisHeight < min) {
269 | min = thisHeight;
270 | }
271 | }
272 | } else {
273 | // Horizontal bar chart (get minMax width)
274 | for (var i = 0; i < arr.layers.length; i++) {
275 | var thisWidth = arr.layers[i].frame.width; // Max
276 |
277 | if (thisWidth > max) {
278 | max = thisWidth;
279 | } // Min
280 |
281 |
282 | if (min == 0) {
283 | // set min at first run
284 | min = max;
285 | }
286 |
287 | if (thisWidth < min) {
288 | min = thisWidth;
289 | }
290 | }
291 | }
292 |
293 | return [Math.ceil(min), Math.ceil(max)];
294 | }
295 |
296 | function myinput() {
297 | var myMinMax = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [20, 100];
298 | var numOfBars = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "";
299 | var myBarHeightFromSelection = arguments.length > 2 ? arguments[2] : undefined;
300 | var my_isVertical = arguments.length > 3 ? arguments[3] : undefined;
301 | var myresponse = {
302 | code: null,
303 | max: null,
304 | forcetype: false,
305 | numbers: [],
306 | trendTypeInput: null
307 | };
308 |
309 | if (myMinMax.length != 2 || myMinMax[0] == myMinMax[1]) {
310 | if (myMinMax[0] > 100) {
311 | myMinMax = [20, myMinMax[1]];
312 | } else {
313 | myMinMax = [myMinMax[0], 100];
314 | }
315 | }
316 |
317 | if (numOfBars == 0) {
318 | myresponse.code == 1001;
319 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("Sorry buddy", "You need to select multiple rectangles (bars) for this plugin to work.");
320 | }
321 |
322 | if (numOfBars != 0) {
323 | if (numOfBars == 1) {
324 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("Hey, just letting you know", "Most awesome results come when selecting more than 1 bar.");
325 | } // Create initial view panel
326 |
327 |
328 | var width = 260;
329 | var height = 40; // Number input
330 |
331 | var sampleNumbers = myBarHeightFromSelection;
332 | /*
333 | Setup the window
334 | */
335 |
336 | var alert = COSAlertWindow.new();
337 |
338 | if (numOfBars == 1) {
339 | alert.setMessageText("1 layer selected to create bar chart");
340 | } else {
341 | alert.setMessageText("".concat(numOfBars, " layers selected to create bar chart"));
342 | }
343 |
344 | alert.addButtonWithTitle("Run");
345 | alert.addButtonWithTitle("Cancel");
346 | alert.setInformativeText("This is for a bar chart with specific values, rather than random numbers.");
347 | /*
348 | Input
349 | */
350 |
351 | var alert_width = 280;
352 | var numInput_separatorOptions = ["Comma separated", "Space separated", "Tab separated (Excel row)", "Line break separated (Excel column)"];
353 | var numInput_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Paste in your number values", 12, true, NSMakeRect(0, 0, alert_width, 16));
354 | var numInput = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])(sampleNumbers, null, NSMakeRect(0, 0, alert_width, 25));
355 | var numInput_separator = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createDropdown"])([numInput_separatorOptions[0], numInput_separatorOptions[1], numInput_separatorOptions[2], numInput_separatorOptions[3]], NSMakeRect(-2, -1, 170, 30));
356 | alert.addAccessoryView(numInput_label);
357 | alert.addAccessoryView(numInput);
358 | alert.addAccessoryView(numInput_separator);
359 | /*
360 | Bar type: Vertical or horizontal
361 | */
362 |
363 | var bartype_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Vertical or horizontal?", 12, true, NSMakeRect(0, 0, alert_width, 16));
364 | alert.addAccessoryView(bartype_label);
365 | var bartype_radio = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 48));
366 | var buttonFormat;
367 | buttonFormat = NSButtonCell.alloc().init();
368 | buttonFormat.setButtonType(NSRadioButton);
369 | var matrixFormat = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(NSMakeRect(0, 0, 260, 48), NSRadioModeMatrix, buttonFormat, 2, 1);
370 | matrixFormat.setCellSize(CGSizeMake(260, 25));
371 | var bartype_radio1_label = my_isVertical ? "Automatic (vertical detected)" : "Automatic (horizontal detected)";
372 | var bartype_radio2_label = my_isVertical ? "Force horizontal" : "Force vertical";
373 | var cells = matrixFormat.cells();
374 | cells.objectAtIndex(0).setTitle(bartype_radio1_label);
375 | cells.objectAtIndex(1).setTitle(bartype_radio2_label);
376 | bartype_radio.addSubview(matrixFormat);
377 | alert.addAccessoryView(bartype_radio);
378 | /*
379 | Options
380 | */
381 |
382 | var optionsView_height = 85;
383 | var optionsView = NSView.alloc().initWithFrame(NSMakeRect(0, 0, alert_width, optionsView_height));
384 | var optionsLabel = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Do you want to scale the values?", 12, true, NSMakeRect(0, optionsView_height - 26, alert_width, 16)); //var optionsLabel_inlineNote = createLabel("(optional)", 12, false, NSMakeRect(215, optionsView_height - 26, alert_width, 16), 0.3);
385 |
386 | var option1_textField = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])("", "e.g. 1.5", NSMakeRect(0, optionsView_height - 60, 120, 25));
387 | var option1_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Multiply by", 12, false, NSMakeRect(0, optionsView_height - 79, 130, 16));
388 | var option2_textField = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])("", "e.g. " + 100, NSMakeRect(140, optionsView_height - 60, 120, 25)); // prev version showed myMinMax[1] as option
389 |
390 | var option2_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("or set max height (px)", 12, false, NSMakeRect(140, optionsView_height - 79, 130, 16)); //var options_info = createLabel("You have the option to define the scaling in case the supplied values don't match your desired pixel values. You can either define a multiplier or set a maximum bar height in pixel.", 11, false, NSMakeRect(0, 0, 260, 16*4))
391 |
392 | var options_info = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Scale data values in case the supplied numbers don't match the desired pixel values.", 11, false, NSMakeRect(0, 0, 260, 16 * 2));
393 | optionsView.addSubview(optionsLabel); //optionsView.addSubview(optionsLabel_inlineNote);
394 |
395 | optionsView.addSubview(option1_textField);
396 | optionsView.addSubview(option1_label);
397 | optionsView.addSubview(option2_textField);
398 | optionsView.addSubview(option2_label);
399 | alert.addAccessoryView(optionsView); // alert.addAccessoryView(options_info)
400 |
401 | /*
402 | Key navigation (popup)
403 | */
404 |
405 | alert.alert().window().setInitialFirstResponder(numInput);
406 | numInput.setNextKeyView(option1_textField);
407 | option1_textField.setNextKeyView(option2_textField);
408 | option2_textField.setNextKeyView(numInput);
409 | /*
410 | Note
411 | */
412 |
413 | var note_line1 = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Please make sure proportional scaling is disabled", 11, false, NSMakeRect(0, 0, alert_width + 10, 16), 0.3);
414 | alert.addAccessoryView(note_line1);
415 | /*
416 | RESPONSE
417 | */
418 |
419 | var responseCode = alert.runModal();
420 |
421 | if (responseCode == 1000) {
422 | myresponse.code = 1000; // OK
423 | // Separator
424 |
425 | var sep = ",";
426 | var sep_input = numInput_separator.titleOfSelectedItem();
427 |
428 | if (sep_input == numInput_separatorOptions[1]) {
429 | sep = " ";
430 | }
431 |
432 | if (sep_input == numInput_separatorOptions[2]) {
433 | sep = "\t";
434 | } else if (sep_input == numInput_separatorOptions[3]) {
435 | sep = "\n";
436 | } // Numbers
437 |
438 |
439 | var numbers_str = "";
440 |
441 | if (numInput.stringValue() == "") {
442 | numbers_str = sampleNumbers;
443 | } else {
444 | numbers_str = numInput.stringValue();
445 | }
446 |
447 | var numbers_arr = numbers_str.split(sep);
448 |
449 | for (var i = 0; i < numbers_arr.length; i++) {
450 | myresponse.numbers.push(parseFloat(numbers_arr[i]));
451 | } // Force bar chart type
452 |
453 |
454 | var forcetype_index = matrixFormat.cells().indexOfObject(matrixFormat.selectedCell());
455 | myresponse.forcetype = forcetype_index == 0 ? false : true; // Options
456 |
457 | if (option2_textField.stringValue() != "") {
458 | // Option 2: Set max height
459 | myresponse.scaleType = 2;
460 | myresponse.scaleValue = parseFloat(option2_textField.stringValue());
461 | } else if (option1_textField.stringValue() != "") {
462 | // Option 1: Multiplier
463 | myresponse.scaleType = 1;
464 | myresponse.scaleValue = parseFloat(option1_textField.stringValue());
465 | } else {
466 | myresponse.scaleType = 0;
467 | }
468 | } else {
469 | // Cancel
470 | myresponse.code = 1001;
471 | }
472 |
473 | myresponse.max = myresponse.numbers.reduce(function (a, b) {
474 | return Math.max(a, b);
475 | });
476 | }
477 |
478 | return myresponse;
479 | }
480 |
481 | /***/ }),
482 |
483 | /***/ "./src/utils.js":
484 | /*!**********************!*\
485 | !*** ./src/utils.js ***!
486 | \**********************/
487 | /*! exports provided: getSymbolInstances, onlyUnique, iterativeGapFilling, createLabel, createTextField, createDropdown, createCheckbox, getValFromLayerName, renameLayer, isVerticalBarchart, getBarHeight */
488 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
489 |
490 | "use strict";
491 | __webpack_require__.r(__webpack_exports__);
492 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSymbolInstances", function() { return getSymbolInstances; });
493 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onlyUnique", function() { return onlyUnique; });
494 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iterativeGapFilling", function() { return iterativeGapFilling; });
495 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLabel", function() { return createLabel; });
496 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextField", function() { return createTextField; });
497 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createDropdown", function() { return createDropdown; });
498 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createCheckbox", function() { return createCheckbox; });
499 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getValFromLayerName", function() { return getValFromLayerName; });
500 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renameLayer", function() { return renameLayer; });
501 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isVerticalBarchart", function() { return isVerticalBarchart; });
502 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBarHeight", function() { return getBarHeight; });
503 | function getSymbolInstances(source, symbolMaster) {
504 | // https://github.com/sonburn/
505 | var symbolInstances = NSMutableArray.array();
506 | source.sketchObject.pages().forEach(function (page) {
507 | var predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@', 'MSSymbolInstance', symbolMaster.sketchObject.objectID());
508 | page.children().filteredArrayUsingPredicate(predicate).forEach(function (instance) {
509 | return symbolInstances.addObject(instance);
510 | });
511 | });
512 | return symbolInstances;
513 | }
514 | function onlyUnique(value, index, self) {
515 | return self.indexOf(value) === index;
516 | }
517 | function iterativeGapFilling(array, length) {
518 | var newArray = [];
519 |
520 | for (var i = 0; i < length; i++) {
521 | var loop = Math.floor(i / array.length);
522 | var index = i - loop * array.length;
523 | newArray.push(array[index]);
524 | }
525 |
526 | return newArray;
527 | }
528 | /**********************/
529 |
530 | /* POPUP */
531 |
532 | /**********************/
533 |
534 | /*
535 | Utils from Marc Bouchenoire
536 | for easier UI design
537 | https://github.com/bouchenoiremarc
538 | */
539 |
540 | function createLabel(text, fontSize, bold, frame, opacity) {
541 | var label = NSTextField.alloc().initWithFrame(frame);
542 | label.setStringValue(text);
543 | label.setFont(bold ? NSFont.boldSystemFontOfSize(fontSize) : NSFont.systemFontOfSize(fontSize));
544 | label.setBezeled(false);
545 | label.setDrawsBackground(false);
546 | label.setEditable(false);
547 | label.setSelectable(false);
548 | if (opacity) label.setAlphaValue(opacity);
549 | return label;
550 | }
551 | function createTextField(value, placeholder, frame) {
552 | var textfield = NSTextField.alloc().initWithFrame(frame);
553 | textfield.cell().setWraps(false);
554 | textfield.cell().setScrollable(true);
555 | textfield.setStringValue(value);
556 | if (placeholder) textfield.setPlaceholderString(placeholder);
557 | return textfield;
558 | }
559 | function createDropdown(values, frame) {
560 | var dropdown = NSPopUpButton.alloc().initWithFrame(frame);
561 | dropdown.addItemsWithTitles(values);
562 | return dropdown;
563 | }
564 | function createCheckbox(text, checked, frame) {
565 | checked = checked == false ? NSOffState : NSOnState;
566 | var checkbox = NSButton.alloc().initWithFrame(frame);
567 | checkbox.setButtonType(NSSwitchButton);
568 | checkbox.setBezelStyle(0);
569 | checkbox.setTitle(text);
570 | checkbox.setState(checked);
571 | return checkbox;
572 | }
573 | /**********************/
574 |
575 | /* VAL IN LAYER NAME */
576 |
577 | /**********************/
578 |
579 | function getValFromLayerName(name) {
580 | var a = name.split("{:");
581 |
582 | if (a.length == 1) {
583 | return false;
584 | }
585 |
586 | var b = a[1].split(":}");
587 | var val = parseFloat(b[0]);
588 |
589 | if (isNaN(val)) {
590 | return false;
591 | }
592 |
593 | return val;
594 | }
595 | function renameLayer(name, newVal) {
596 | var a = name.split("{:");
597 | var newName = name + " {:" + newVal + ":}";
598 |
599 | if (a.length > 1) {
600 | var b = a[1].split(":}");
601 |
602 | if (b.length == 1) {
603 | return newName;
604 | }
605 |
606 | var newName = a[0] + "{:" + newVal + ":}" + b[1];
607 | }
608 |
609 | return newName;
610 | }
611 | /**********************/
612 |
613 | /* BARCHART */
614 |
615 | /**********************/
616 |
617 | function isVerticalBarchart(arr) {
618 | // arr needs to be doc.selectedLayers
619 | var isVertical = true;
620 |
621 | if (arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y) {
622 | // It's horizontal if
623 | // 1. First two bars share same x value (works for positive values)
624 | if (arr.layers[0].frame.x == arr.layers[1].frame.x) {
625 | isVertical = false;
626 | } // 2. Same y-baseline (works if first value is negative)
627 | // and they share same height
628 | // ! Needs check if first / second val is negative
629 | else if (arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
630 | isVertical = false;
631 | } else if (arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
632 | isVertical = false;
633 | }
634 | }
635 |
636 | return isVertical;
637 | }
638 | /**********************/
639 |
640 | /* NON-RANDO BARCHART */
641 |
642 | /**********************/
643 |
644 | function getBarHeight(arr, isVertical) {
645 | // arr needs to be doc.selectedLayers
646 | var barLength_str = "";
647 |
648 | for (var i = 0; i < arr.layers.length; i++) {
649 | var thisLength = undefined;
650 |
651 | if (isVertical) {
652 | thisLength = arr.layers[i].frame.height.toFixed(2); // reduce to 2 decimals
653 | } else {
654 | thisLength = arr.layers[i].frame.width.toFixed(2); // reduce to 2 decimals
655 | }
656 |
657 | thisLength = parseFloat(thisLength); // to remove decimals from integers
658 |
659 | if (i == 0) {
660 | barLength_str = "" + thisLength;
661 | } else {
662 | barLength_str = barLength_str + "," + thisLength;
663 | }
664 | }
665 |
666 | return barLength_str;
667 | }
668 |
669 | /***/ }),
670 |
671 | /***/ "sketch":
672 | /*!*************************!*\
673 | !*** external "sketch" ***!
674 | \*************************/
675 | /*! no static exports found */
676 | /***/ (function(module, exports) {
677 |
678 | module.exports = require("sketch");
679 |
680 | /***/ })
681 |
682 | /******/ });
683 | if (key === 'default' && typeof exports === 'function') {
684 | exports(context);
685 | } else {
686 | exports[key](context);
687 | }
688 | }
689 | that['onRun'] = __skpm_run.bind(this, 'default')
690 |
691 | //# sourceMappingURL=nonrandom-barchart.js.map
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Sketch/randomfill.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/randomfill.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./src/randomfill.js":
95 | /*!***************************!*\
96 | !*** ./src/randomfill.js ***!
97 | \***************************/
98 | /*! exports provided: default */
99 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
100 |
101 | "use strict";
102 | __webpack_require__.r(__webpack_exports__);
103 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch */ "sketch");
104 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch__WEBPACK_IMPORTED_MODULE_0__);
105 | /* harmony import */ var _utils_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./utils.js */ "./src/utils.js");
106 |
107 |
108 | /* harmony default export */ __webpack_exports__["default"] = (function () {
109 | log('~~ Run Chippen charts ~~');
110 | var doc = sketch__WEBPACK_IMPORTED_MODULE_0___default.a.getSelectedDocument();
111 | var selectedLayers = doc.selectedLayers; // Elements with these types will get fill colour applied
112 |
113 | var el_has_fillcolor = ["Rectangle", "ShapePath", "Shape"];
114 | var el_has_textcolor = ["Text"]; // Default values for popup
115 |
116 | var defaultCol1 = "#eeeeee";
117 | var defaultCol2 = "#891c55";
118 | var defaultCategories = 5;
119 | /*
120 | CHECK SELECTION
121 | */
122 |
123 | if (selectedLayers.length == 0) {
124 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.alert("Chippencharts", 'Please select at least 1 shape or text layers to apply the random fill colours to.');
125 | return false;
126 | }
127 | /*
128 | Setup the popup window
129 | */
130 |
131 |
132 | var popup = COSAlertWindow.new();
133 | popup.setMessageText("Random fill");
134 | popup.addButtonWithTitle("Run");
135 | popup.addButtonWithTitle("Cancel");
136 | popup.setInformativeText("Get as many colours as you want between two colours and randomly apply as fill to selected layers.");
137 | /*
138 | Input
139 | */
140 |
141 | var popup_width = 280;
142 | var colInput_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("Paste in your two colour values", 12, true, NSMakeRect(0, 0, popup_width, 16));
143 | var col_view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, popup_width, 25));
144 | var col1Input = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])(defaultCol1, null, NSMakeRect(0, 0, 130, 25));
145 | var col2Input = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])(defaultCol2, null, NSMakeRect(150, 0, 130, 25));
146 | var categories_label = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createLabel"])("How many random colours do you want?", 12, true, NSMakeRect(0, 0, popup_width, 16));
147 | var categoriesInput = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createTextField"])(defaultCategories, null, NSMakeRect(0, 0, 130, 25));
148 | var sort_checkbox = Object(_utils_js__WEBPACK_IMPORTED_MODULE_1__["createCheckbox"])("Use layer order instead of random order", false, NSMakeRect(-2, -1, 280, 24));
149 | popup.addAccessoryView(colInput_label);
150 | col_view.addSubview(col1Input);
151 | col_view.addSubview(col2Input);
152 | popup.addAccessoryView(col_view);
153 | popup.addAccessoryView(categories_label);
154 | popup.addAccessoryView(categoriesInput);
155 | popup.addAccessoryView(sort_checkbox);
156 | popup.alert().window().setInitialFirstResponder(col1Input);
157 | col1Input.setNextKeyView(col2Input);
158 | col2Input.setNextKeyView(categoriesInput);
159 | categoriesInput.setNextKeyView(col1Input);
160 | /*
161 | RESPONSE
162 | */
163 |
164 | var responseCode = popup.runModal();
165 |
166 | if (responseCode != 1000) {
167 | // User clicked "Cancel"
168 | return false;
169 | }
170 |
171 | var col1 = removeHash(col1Input.stringValue());
172 | var col2 = removeHash(col2Input.stringValue());
173 | var num_of_colours = parseFloat(categoriesInput.stringValue());
174 | var apply_by_layer_order = Number(sort_checkbox.state()) == 1 ? true : false;
175 | /*
176 | CALCULATE COLOURS AND APPLY
177 | */
178 |
179 | var col1_rgb = hexToRGB(col1);
180 | var col2_rgb = hexToRGB(col2);
181 | var colours = [col1]; // start colour
182 |
183 | for (var i = 0; i < num_of_colours - 2; i++) {
184 | var new_rgb = [];
185 |
186 | for (var j = 0; j < 3; j++) {
187 | var new_diff = col1_rgb[j] - col2_rgb[j];
188 | var new_dir = new_diff >= 0 ? -1 : 1;
189 | var new_add = Math.abs(new_diff) / (num_of_colours - 1);
190 | var new_dim = col1_rgb[j] + new_dir * (i + 1) * new_add;
191 | new_rgb.push(Math.round(new_dim));
192 | }
193 |
194 | colours.push(rgbToHex(new_rgb));
195 | }
196 |
197 | colours.push(col2); // last colour
198 | // Apply new colours to selection
199 |
200 | for (var i = 0; i < selectedLayers.layers.length; i++) {
201 | var random_index = Math.floor(Math.random() * (+colours.length - +0)) + +0;
202 | var order_index = Math.floor(i * ((colours.length - 1) / (selectedLayers.layers.length - 1)));
203 | var col_index = apply_by_layer_order ? order_index : random_index;
204 | var random_col = hex_9(colours[col_index]);
205 |
206 | if (el_has_fillcolor.includes(selectedLayers.layers[i].type)) {
207 | // Change fill if it's shape layer
208 | selectedLayers.layers[i].style.fills[0].color = random_col;
209 | } else if (el_has_textcolor.includes(selectedLayers.layers[i].type)) {
210 | // Change fill if it's a text layer
211 | selectedLayers.layers[i].style.textColor = random_col;
212 | }
213 | }
214 | });
215 |
216 | function hexToRGB(hex) {
217 | var rgb = [];
218 |
219 | for (var i = 0; i < 3; i++) {
220 | var sub1 = hex.substring(2 * i, 2 + 2 * i);
221 | var v = parseInt(sub1, 16);
222 | rgb.push(v);
223 | }
224 |
225 | return rgb;
226 | }
227 |
228 | function hex_6(hex) {
229 | // #d8d8d8ff > d8d8d8
230 | return hex.substr(1, 6);
231 | }
232 |
233 | function hex_9(hex_6) {
234 | // d8d8d8 > #d8d8d8ff
235 | return "#" + hex_6 + "ff";
236 | }
237 |
238 | function rgbToHex(arr) {
239 | var hex = "";
240 |
241 | for (var i = 0; i < 3; i++) {
242 | var sub = arr[i].toString(16).toUpperCase();
243 | var padsub = ('0' + sub).slice(-2);
244 | hex = hex + padsub;
245 | }
246 |
247 | return hex;
248 | }
249 |
250 | function removeHash(hex) {
251 | return hex.substr(0, 1) == "#" ? hex.substr(1, 6) : hex;
252 | }
253 |
254 | /***/ }),
255 |
256 | /***/ "./src/utils.js":
257 | /*!**********************!*\
258 | !*** ./src/utils.js ***!
259 | \**********************/
260 | /*! exports provided: getSymbolInstances, onlyUnique, iterativeGapFilling, createLabel, createTextField, createDropdown, createCheckbox, getValFromLayerName, renameLayer, isVerticalBarchart, getBarHeight */
261 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
262 |
263 | "use strict";
264 | __webpack_require__.r(__webpack_exports__);
265 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getSymbolInstances", function() { return getSymbolInstances; });
266 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "onlyUnique", function() { return onlyUnique; });
267 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "iterativeGapFilling", function() { return iterativeGapFilling; });
268 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createLabel", function() { return createLabel; });
269 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createTextField", function() { return createTextField; });
270 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createDropdown", function() { return createDropdown; });
271 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "createCheckbox", function() { return createCheckbox; });
272 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getValFromLayerName", function() { return getValFromLayerName; });
273 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "renameLayer", function() { return renameLayer; });
274 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isVerticalBarchart", function() { return isVerticalBarchart; });
275 | /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getBarHeight", function() { return getBarHeight; });
276 | function getSymbolInstances(source, symbolMaster) {
277 | // https://github.com/sonburn/
278 | var symbolInstances = NSMutableArray.array();
279 | source.sketchObject.pages().forEach(function (page) {
280 | var predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@', 'MSSymbolInstance', symbolMaster.sketchObject.objectID());
281 | page.children().filteredArrayUsingPredicate(predicate).forEach(function (instance) {
282 | return symbolInstances.addObject(instance);
283 | });
284 | });
285 | return symbolInstances;
286 | }
287 | function onlyUnique(value, index, self) {
288 | return self.indexOf(value) === index;
289 | }
290 | function iterativeGapFilling(array, length) {
291 | var newArray = [];
292 |
293 | for (var i = 0; i < length; i++) {
294 | var loop = Math.floor(i / array.length);
295 | var index = i - loop * array.length;
296 | newArray.push(array[index]);
297 | }
298 |
299 | return newArray;
300 | }
301 | /**********************/
302 |
303 | /* POPUP */
304 |
305 | /**********************/
306 |
307 | /*
308 | Utils from Marc Bouchenoire
309 | for easier UI design
310 | https://github.com/bouchenoiremarc
311 | */
312 |
313 | function createLabel(text, fontSize, bold, frame, opacity) {
314 | var label = NSTextField.alloc().initWithFrame(frame);
315 | label.setStringValue(text);
316 | label.setFont(bold ? NSFont.boldSystemFontOfSize(fontSize) : NSFont.systemFontOfSize(fontSize));
317 | label.setBezeled(false);
318 | label.setDrawsBackground(false);
319 | label.setEditable(false);
320 | label.setSelectable(false);
321 | if (opacity) label.setAlphaValue(opacity);
322 | return label;
323 | }
324 | function createTextField(value, placeholder, frame) {
325 | var textfield = NSTextField.alloc().initWithFrame(frame);
326 | textfield.cell().setWraps(false);
327 | textfield.cell().setScrollable(true);
328 | textfield.setStringValue(value);
329 | if (placeholder) textfield.setPlaceholderString(placeholder);
330 | return textfield;
331 | }
332 | function createDropdown(values, frame) {
333 | var dropdown = NSPopUpButton.alloc().initWithFrame(frame);
334 | dropdown.addItemsWithTitles(values);
335 | return dropdown;
336 | }
337 | function createCheckbox(text, checked, frame) {
338 | checked = checked == false ? NSOffState : NSOnState;
339 | var checkbox = NSButton.alloc().initWithFrame(frame);
340 | checkbox.setButtonType(NSSwitchButton);
341 | checkbox.setBezelStyle(0);
342 | checkbox.setTitle(text);
343 | checkbox.setState(checked);
344 | return checkbox;
345 | }
346 | /**********************/
347 |
348 | /* VAL IN LAYER NAME */
349 |
350 | /**********************/
351 |
352 | function getValFromLayerName(name) {
353 | var a = name.split("{:");
354 |
355 | if (a.length == 1) {
356 | return false;
357 | }
358 |
359 | var b = a[1].split(":}");
360 | var val = parseFloat(b[0]);
361 |
362 | if (isNaN(val)) {
363 | return false;
364 | }
365 |
366 | return val;
367 | }
368 | function renameLayer(name, newVal) {
369 | var a = name.split("{:");
370 | var newName = name + " {:" + newVal + ":}";
371 |
372 | if (a.length > 1) {
373 | var b = a[1].split(":}");
374 |
375 | if (b.length == 1) {
376 | return newName;
377 | }
378 |
379 | var newName = a[0] + "{:" + newVal + ":}" + b[1];
380 | }
381 |
382 | return newName;
383 | }
384 | /**********************/
385 |
386 | /* BARCHART */
387 |
388 | /**********************/
389 |
390 | function isVerticalBarchart(arr) {
391 | // arr needs to be doc.selectedLayers
392 | var isVertical = true;
393 |
394 | if (arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y) {
395 | // It's horizontal if
396 | // 1. First two bars share same x value (works for positive values)
397 | if (arr.layers[0].frame.x == arr.layers[1].frame.x) {
398 | isVertical = false;
399 | } // 2. Same y-baseline (works if first value is negative)
400 | // and they share same height
401 | // ! Needs check if first / second val is negative
402 | else if (arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
403 | isVertical = false;
404 | } else if (arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height) {
405 | isVertical = false;
406 | }
407 | }
408 |
409 | return isVertical;
410 | }
411 | /**********************/
412 |
413 | /* NON-RANDO BARCHART */
414 |
415 | /**********************/
416 |
417 | function getBarHeight(arr, isVertical) {
418 | // arr needs to be doc.selectedLayers
419 | var barLength_str = "";
420 |
421 | for (var i = 0; i < arr.layers.length; i++) {
422 | var thisLength = undefined;
423 |
424 | if (isVertical) {
425 | thisLength = arr.layers[i].frame.height.toFixed(2); // reduce to 2 decimals
426 | } else {
427 | thisLength = arr.layers[i].frame.width.toFixed(2); // reduce to 2 decimals
428 | }
429 |
430 | thisLength = parseFloat(thisLength); // to remove decimals from integers
431 |
432 | if (i == 0) {
433 | barLength_str = "" + thisLength;
434 | } else {
435 | barLength_str = barLength_str + "," + thisLength;
436 | }
437 | }
438 |
439 | return barLength_str;
440 | }
441 |
442 | /***/ }),
443 |
444 | /***/ "sketch":
445 | /*!*************************!*\
446 | !*** external "sketch" ***!
447 | \*************************/
448 | /*! no static exports found */
449 | /***/ (function(module, exports) {
450 |
451 | module.exports = require("sketch");
452 |
453 | /***/ })
454 |
455 | /******/ });
456 | if (key === 'default' && typeof exports === 'function') {
457 | exports(context);
458 | } else {
459 | exports[key](context);
460 | }
461 | }
462 | that['onRun'] = __skpm_run.bind(this, 'default')
463 |
464 | //# sourceMappingURL=randomfill.js.map
--------------------------------------------------------------------------------
/chippen-charts.sketchplugin/Contents/Sketch/randomfill.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/randomfill.js","webpack://exports/./src/utils.js","webpack://exports/external \"sketch\""],"names":["log","doc","sketch","getSelectedDocument","selectedLayers","el_has_fillcolor","el_has_textcolor","defaultCol1","defaultCol2","defaultCategories","length","UI","alert","popup","COSAlertWindow","new","setMessageText","addButtonWithTitle","setInformativeText","popup_width","colInput_label","createLabel","NSMakeRect","col_view","NSView","alloc","initWithFrame","col1Input","createTextField","col2Input","categories_label","categoriesInput","sort_checkbox","createCheckbox","addAccessoryView","addSubview","window","setInitialFirstResponder","setNextKeyView","responseCode","runModal","col1","removeHash","stringValue","col2","num_of_colours","parseFloat","apply_by_layer_order","Number","state","col1_rgb","hexToRGB","col2_rgb","colours","i","new_rgb","j","new_diff","new_dir","new_add","Math","abs","new_dim","push","round","rgbToHex","layers","random_index","floor","random","order_index","col_index","random_col","hex_9","includes","type","style","fills","color","textColor","hex","rgb","sub1","substring","v","parseInt","hex_6","substr","arr","sub","toString","toUpperCase","padsub","slice","getSymbolInstances","source","symbolMaster","symbolInstances","NSMutableArray","array","sketchObject","pages","forEach","page","predicate","NSPredicate","predicateWithFormat","objectID","children","filteredArrayUsingPredicate","instance","addObject","onlyUnique","value","index","self","indexOf","iterativeGapFilling","newArray","loop","text","fontSize","bold","frame","opacity","label","NSTextField","setStringValue","setFont","NSFont","boldSystemFontOfSize","systemFontOfSize","setBezeled","setDrawsBackground","setEditable","setSelectable","setAlphaValue","placeholder","textfield","cell","setWraps","setScrollable","setPlaceholderString","createDropdown","values","dropdown","NSPopUpButton","addItemsWithTitles","checked","NSOffState","NSOnState","checkbox","NSButton","setButtonType","NSSwitchButton","setBezelStyle","setTitle","setState","getValFromLayerName","name","a","split","b","val","isNaN","renameLayer","newVal","newName","isVerticalBarchart","isVertical","y","x","width","height","getBarHeight","barLength_str","thisLength","undefined","toFixed"],"mappings":"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","file":"randomfill.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/randomfill.js\");\n","import sketch from 'sketch'\nimport { createLabel, createTextField, createCheckbox, onlyUnique } from \"./utils.js\";\n\nexport default function() {\n\tlog('~~ Run Chippen charts ~~')\n\tconst doc = sketch.getSelectedDocument()\n\tconst selectedLayers = doc.selectedLayers;\n\n\t// Elements with these types will get fill colour applied\n\tconst el_has_fillcolor = [\"Rectangle\", \"ShapePath\", \"Shape\"]\n\tconst el_has_textcolor = [\"Text\"]\n\n\t// Default values for popup\n\tconst defaultCol1 = \"#eeeeee\";\n\tconst defaultCol2 = \"#891c55\";\n\tconst defaultCategories = 5;\n\t\n\n\t/*\n\t\tCHECK SELECTION\n\t*/\n\t\n\tif (selectedLayers.length == 0) {\n\t\tsketch.UI.alert(\"Chippencharts\",'Please select at least 1 shape or text layers to apply the random fill colours to.');\n\t\treturn false;\n\t}\n\n\n\t/*\n\t\tSetup the popup window\n\t*/\n\n\tvar popup = COSAlertWindow.new()\n\tpopup.setMessageText(\"Random fill\")\n\tpopup.addButtonWithTitle(\"Run\");\n\tpopup.addButtonWithTitle(\"Cancel\");\n\tpopup.setInformativeText(`Get as many colours as you want between two colours and randomly apply as fill to selected layers.`);\n\n\n\t/*\n\t\tInput\n \t*/\n\n \tconst popup_width = 280;\n\n\tvar colInput_label = createLabel(\"Paste in your two colour values\", 12, true, NSMakeRect(0, 0, popup_width, 16));\n \t\n\tvar col_view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, popup_width, 25));\n \tvar col1Input = createTextField(defaultCol1, null, NSMakeRect(0, 0, 130, 25));\n \tvar col2Input = createTextField(defaultCol2, null, NSMakeRect(150, 0, 130, 25));\n \t\n \tvar categories_label = createLabel(\"How many random colours do you want?\", 12, true, NSMakeRect(0, 0, popup_width, 16));\n \tvar categoriesInput = createTextField(defaultCategories, null, NSMakeRect(0, 0, 130, 25));\n\n\tvar sort_checkbox = createCheckbox(\"Use layer order instead of random order\", false, NSMakeRect(-2, -1, 280, 24));\n\t\n\tpopup.addAccessoryView(colInput_label)\n\tcol_view.addSubview(col1Input)\n\tcol_view.addSubview(col2Input)\n \tpopup.addAccessoryView(col_view);\n\n \tpopup.addAccessoryView(categories_label);\n \tpopup.addAccessoryView(categoriesInput);\n\n \tpopup.addAccessoryView(sort_checkbox);\n\n \tpopup.alert().window().setInitialFirstResponder(col1Input);\n\tcol1Input.setNextKeyView(col2Input)\n\tcol2Input.setNextKeyView(categoriesInput)\n\tcategoriesInput.setNextKeyView(col1Input)\n\n\n \t/*\n\t\tRESPONSE\n\t*/\n\n\tvar responseCode = popup.runModal();\n\t\n\tif(responseCode != 1000){\n\n\t\t// User clicked \"Cancel\"\n\t\treturn false;\n\t}\n\n\tvar col1 = removeHash(col1Input.stringValue());\n\tvar col2 = removeHash(col2Input.stringValue());\n\tvar num_of_colours = parseFloat(categoriesInput.stringValue());\n\tvar apply_by_layer_order = Number(sort_checkbox.state()) == 1 ? true : false;\n\t\n\n\t/*\n\t\tCALCULATE COLOURS AND APPLY\n\t*/\n\n\tvar col1_rgb = hexToRGB(col1);\n\tvar col2_rgb = hexToRGB(col2);\n\n\tvar colours = [col1] // start colour\n\n\tfor(var i=0; i<(num_of_colours-2); i++){\n\n\t\tvar new_rgb = []\n\n\t\tfor(var j=0; j<3; j++){\n\t\t\t\n\n\t\t\tvar new_diff = col1_rgb[j] - col2_rgb[j];\n\t\t\tvar new_dir = new_diff >=0 ? -1 : 1;\n\n\t\t\tvar new_add = Math.abs(new_diff) / (num_of_colours-1);\n\t\t\tvar new_dim = col1_rgb[j] + new_dir*(i+1)*new_add;\n\n\t\t\tnew_rgb.push(Math.round(new_dim))\n\t\t}\n\t\tcolours.push(rgbToHex(new_rgb))\n\t}\n\n\tcolours.push(col2) // last colour\n\n\n\t// Apply new colours to selection\n\tfor(var i = 0; i d8d8d8\n\treturn hex.substr(1,6);\n}\n\nfunction hex_9 (hex_6){\n\t// d8d8d8 > #d8d8d8ff\n\treturn \"#\" + hex_6 + \"ff\";\n}\n\nfunction rgbToHex(arr){\n\tvar hex = \"\";\n\tfor(var i=0; i<3; i++){\n\t\tvar sub = arr[i].toString(16).toUpperCase();\n\t\tvar padsub = ('0'+sub).slice(-2);\n\t\thex = hex + padsub\n\t}\n\treturn hex;\n}\n\nfunction removeHash(hex){\n\treturn hex.substr(0,1)==\"#\" ? hex.substr(1,6) : hex;\n\n}","export function getSymbolInstances(source,symbolMaster) {\n\t// https://github.com/sonburn/\n\tvar symbolInstances = NSMutableArray.array();\n\n\tsource.sketchObject.pages().forEach(function(page){\n\t\tvar predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@','MSSymbolInstance',symbolMaster.sketchObject.objectID());\n\n\t\tpage.children().filteredArrayUsingPredicate(predicate).forEach(instance => symbolInstances.addObject(instance));\n\t});\n\n\treturn symbolInstances;\n}\n\nexport function onlyUnique(value, index, self) { \n return self.indexOf(value) === index;\n}\n\nexport function iterativeGapFilling(array, length){\n\tvar newArray = [];\n\tfor(var i=0; i 1){\n\t\tvar b = a[1].split(\":}\");\n\t\tif(b.length == 1){return newName;}\n\t\tvar newName = a[0] + \"{:\" + newVal + \":}\" + b[1];\n\t}\n\n\treturn newName\n}\n\n\n/**********************/\n/* BARCHART */\n/**********************/\n\nexport function isVerticalBarchart(arr){\n\t// arr needs to be doc.selectedLayers\n\tvar isVertical = true\n\tif(arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y){\n\t\t// It's horizontal if\n\t\t// 1. First two bars share same x value (works for positive values)\n\t\tif(arr.layers[0].frame.x == arr.layers[1].frame.x){\n\t\t\tisVertical = false;\n\t\t}\n\t\t// 2. Same y-baseline (works if first value is negative) \n\t\t// and they share same height\n\t\t// ! Needs check if first / second val is negative\n\t\telse if(arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){\n\t\t\tisVertical = false;\t\n\t\t}\n\t\telse if(arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){\n\t\t\tisVertical = false;\t\n\t\t}\n\t}\n\treturn isVertical\n}\n\n\n/**********************/\n/* NON-RANDO BARCHART */\n/**********************/\n\nexport function getBarHeight(arr, isVertical){\n\t// arr needs to be doc.selectedLayers\n\tvar barLength_str = \"\"\n\t\n\tfor(var i=0; i=3.0"
6 | },
7 | "description": "Bar chart creator for your mockups using random or user defined data. Change the size of selected rectangles. Works for both horizontal and vertical bar charts. Made with love in Chippendale.",
8 | "skpm": {
9 | "name": "Chippen charts",
10 | "manifest": "src/manifest.json",
11 | "main": "chippen-charts.sketchplugin",
12 | "assets": [
13 | "assets/**/*"
14 | ]
15 | },
16 | "scripts": {
17 | "build": "skpm-build",
18 | "watch": "skpm-build --watch",
19 | "start": "skpm-build --watch --run",
20 | "postinstall": "npm run build && skpm-link"
21 | },
22 | "devDependencies": {
23 | "@skpm/builder": "^0.5.2"
24 | },
25 | "repository": "https://github.com/smallmultiples/sketch-chippencharts.git",
26 | "author": "Martin von Lupin"
27 | }
28 |
--------------------------------------------------------------------------------
/src/barchart.js:
--------------------------------------------------------------------------------
1 | import sketch from 'sketch'
2 | import { getValFromLayerName, renameLayer, isVerticalBarchart, createLabel } from "./utils.js";
3 | // documentation: https://developer.sketchapp.com/reference/api/
4 |
5 | export default function() {
6 | log('~~ Run Chippen charts ~~')
7 | const doc = sketch.getSelectedDocument()
8 | const selectedLayers = doc.selectedLayers
9 |
10 | /*
11 | Analyse selected layers
12 | */
13 |
14 | var isVertical = isVerticalBarchart(doc.selectedLayers)
15 | var minMax_fromSelection = getMinMax(doc.selectedLayers, isVertical)
16 |
17 |
18 | /*
19 | User input
20 | */
21 |
22 | var response = myinput(minMax_fromSelection, doc.selectedLayers.layers.length, isVertical)
23 | var minMax = [response.min, response.max]
24 | if (response.code !== 1000) {
25 | return
26 | }
27 | var myRandomSlots = []
28 | if(response.trendTypeInput == 0){
29 | // Only for random trend
30 | // Set 2 random bars to min and max
31 | myRandomSlots = twoRandomSlots(selectedLayers.layers.length, 'Random')
32 | }
33 |
34 | // Force other type than detected if user has selected force type
35 | if(response.forcetype){isVertical = !isVertical}
36 |
37 |
38 | /*
39 | UI message
40 | */
41 |
42 | var trendTypeInput_name = [
43 | "random data",
44 | "trend going up ↑ (linear)",
45 | "trend going up ↑ (natural)",
46 | "trend going down ↓ (linear)",
47 | "trend going down ↓ (natural)"
48 | ]
49 |
50 | var isVertical_name = "vertical"
51 | if(!isVertical){isVertical_name = "horizontal"}
52 | sketch.UI.message(`${doc.selectedLayers.length} ${isVertical_name} bars with ${trendTypeInput_name[response.trendTypeInput]} (${minMax[0]}px–${minMax[1]}px)`)
53 |
54 |
55 | /*
56 | Changing size
57 | */
58 |
59 | const firstBarVal = getValFromLayerName(selectedLayers.layers[0].name);
60 | var baseLine = 0;
61 |
62 | if(isVertical){
63 | baseLine = selectedLayers.layers[0].frame.y + selectedLayers.layers[0].frame.height;
64 | // Adjust when first value of existing bar is negative
65 | // Based on layer name
66 | if(firstBarVal < 0){baseLine = baseLine - Math.abs(firstBarVal)};
67 | }else{
68 | if(firstBarVal >= 0){
69 | baseLine = selectedLayers.layers[0].frame.x
70 | }else if(firstBarVal < 0){
71 | baseLine = selectedLayers.layers[0].frame.x + Math.abs(firstBarVal)
72 | }
73 | }
74 |
75 | for(var i = 0; i 0){
126 | // Reposition bars with positive values
127 | selectedLayers.layers[i].frame.y = baseLine - Math.abs(newLength);
128 | }else{
129 | // Reposition bars with negative values
130 | selectedLayers.layers[i].frame.y = baseLine;
131 | }
132 | }else{
133 | // Reset position, just in case
134 | selectedLayers.layers[i].frame.x = baseLine;
135 |
136 | // Change Width
137 | selectedLayers.layers[i].frame.width = Math.abs(newLength);
138 |
139 | // Reposition bars with negative values
140 | if(newLength < 0){
141 | selectedLayers.layers[i].frame.x = selectedLayers.layers[i].frame.x - Math.abs(newLength)
142 | }
143 | }
144 |
145 | // Rename layer
146 | // Example: Rectangle ==> Rectangle {:12:}
147 | selectedLayers.layers[i].name = renameLayer(selectedLayers.layers[i].name, newLength)
148 | }
149 | }
150 |
151 | function getMinMax(arr, isVertical){
152 | // arr needs to be doc.selectedLayers
153 | var min = 0;
154 | var max = 0;
155 |
156 | if(isVertical){
157 | // Vertical bar chart (get minMax height)
158 | for(var i = 0; imax){
162 | max = thisHeight
163 | }
164 | // Min
165 | if(min == 0){
166 | // set min at first runfirst
167 | min = max
168 | }
169 | if(thisHeight < min){
170 | min = thisHeight
171 | }
172 | }
173 | }else{
174 | // Horizontal bar chart (get minMax width)
175 | for(var i = 0; i max){
179 | max = thisWidth
180 | }
181 | // Min
182 | if(min == 0){
183 | // set min at first run
184 | min = max
185 | }
186 | if(thisWidth < min){
187 | min = thisWidth
188 | }
189 | }
190 | }
191 |
192 | return [Math.ceil(min), Math.ceil(max)]
193 | }
194 |
195 | function twoRandomSlots(length, type){
196 | var slotOne = 0
197 | var slotTwo = 0
198 |
199 | if(type=='Random'){
200 | slotOne = Math.floor( Math.random() * length/2)
201 | slotTwo = Math.floor( Math.random() * length/2) + Math.floor(length/2)
202 | }
203 | return [slotOne, slotTwo]
204 | }
205 |
206 |
207 | function myinput(myMinMax=[20,100], numOfBars="", my_isVertical){
208 | var myresponse = {}
209 |
210 | if(myMinMax.length != 2 || myMinMax[0]==myMinMax[1]){
211 | if(myMinMax[0] > 100){
212 | myMinMax = [20,myMinMax[1]]
213 | }else{
214 | myMinMax = [myMinMax[0],100]
215 | }
216 |
217 | }
218 |
219 | if(numOfBars==0){
220 | myresponse.code == 1001
221 | sketch.UI.alert("Sorry buddy", "You need to select multiple rectangles (bars) for this plugin to work.")
222 | }
223 | if(numOfBars!=0){
224 |
225 | if(numOfBars==1){
226 | sketch.UI.alert("Hey, just letting you know", "Most awesome results come when selecting more than 1 bar.")
227 | }
228 |
229 | // Create initial view panel
230 | var width = 280
231 | var height = 40
232 | var view = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, height))
233 |
234 | // Min Max input
235 | var minInput = NSTextField.alloc().initWithFrame(NSMakeRect(0.0, 15.0, 130, 25.0));
236 | minInput.cell().setPlaceholderString(myMinMax[0] + " (min)");
237 | view.addSubview(minInput);
238 |
239 | var maxInput = NSTextField.alloc().initWithFrame(NSMakeRect(150, 15.0, 130, 25.0));
240 | maxInput.cell().setPlaceholderString(myMinMax[1] + " (max)");
241 | view.addSubview(maxInput);
242 |
243 | // Nature of data
244 | var trendTypeInput = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 135))
245 | // Acts like a template (prototype) for our radio buttons
246 | var buttonFormat;
247 | buttonFormat = NSButtonCell.alloc().init();
248 | buttonFormat.setButtonType(NSRadioButton);
249 |
250 | // The matrix will contain all the cells (radio buttons)
251 | var matrixFormat = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(
252 | NSMakeRect(0, 0, 260, 135), // Horizontal position, vertical position, width, height
253 | NSRadioModeMatrix, // This makes the radio buttons work together
254 | buttonFormat,
255 | 5, // 1 row
256 | 1 // 3 columns (for 3 radio buttons)
257 | );
258 |
259 | // Settings the size of the radio buttons
260 | matrixFormat.setCellSize(CGSizeMake(260, 25));
261 |
262 | // Adding the radio buttons to the form
263 | var cells = matrixFormat.cells();
264 | cells.objectAtIndex(0).setTitle("Random");
265 | cells.objectAtIndex(1).setTitle("Trend going up ↑ (linear)");
266 | cells.objectAtIndex(2).setTitle("Trend going up ↑ (natural)");
267 | cells.objectAtIndex(3).setTitle("Trend going down ↓ (linear)");
268 | cells.objectAtIndex(4).setTitle("Trend going down ↓ (natural)");
269 |
270 | // Adding the matrix to the form
271 | trendTypeInput.addSubview(matrixFormat);
272 |
273 |
274 | // Bar type: Vertical or horizontal
275 |
276 | var bartype_label = createLabel("Vertical or horizontal?", 12, true, NSMakeRect(0, 0, width, 16));
277 |
278 | var bartype_radio = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 48))
279 |
280 | var matrixFormat_bartype = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(
281 | NSMakeRect(0, 0, 260, 48),
282 | NSRadioModeMatrix,
283 | buttonFormat, 2, 1
284 | );
285 |
286 | matrixFormat_bartype.setCellSize(CGSizeMake(260, 25));
287 |
288 | var bartype_radio1_label = my_isVertical ? "Automatic (vertical detected)" : "Automatic (horizontal detected)"
289 | var bartype_radio2_label = my_isVertical ? "Force horizontal" : "Force vertical"
290 | var cells_bartype = matrixFormat_bartype.cells();
291 | cells_bartype.objectAtIndex(0).setTitle(bartype_radio1_label);
292 | cells_bartype.objectAtIndex(1).setTitle(bartype_radio2_label);
293 |
294 | bartype_radio.addSubview(matrixFormat_bartype);
295 |
296 |
297 | // Setup the window
298 | var alert = COSAlertWindow.new()
299 | if(numOfBars==1){
300 | alert.setMessageText(`Create your random bar chart \nwith 1 selected layer`)
301 | }else{
302 | alert.setMessageText(`Create your random bar chart \nwith ${numOfBars} selected layers`)
303 | }
304 |
305 | alert.addButtonWithTitle("Run")
306 | alert.addButtonWithTitle("Cancel")
307 | alert.setInformativeText(`This is for a bar chart where random values are applied \nto the layers of your selection.`)
308 |
309 | var extrema_label = createLabel("Define extrema of bars", 12, true, NSMakeRect(0, 0, width, 16));
310 | alert.addAccessoryView(extrema_label)
311 |
312 | //alert.addTextLabelWithValue("Define extrema of bars");
313 | alert.addAccessoryView(view)
314 |
315 | var trend_label = createLabel("Specify the desired trend", 12, true, NSMakeRect(0, 0, width, 16));
316 | alert.addAccessoryView(trend_label)
317 | //alert.addTextLabelWithValue("Specify the desired trend");
318 | alert.addAccessoryView(trendTypeInput)
319 |
320 | alert.addAccessoryView(bartype_label);
321 | alert.addAccessoryView(bartype_radio)
322 |
323 | /*
324 | Key navigation (popup)
325 | */
326 |
327 | alert.alert().window().setInitialFirstResponder(minInput)
328 | minInput.setNextKeyView(maxInput)
329 | maxInput.setNextKeyView(minInput)
330 |
331 |
332 | /*
333 | Note
334 | */
335 | var note_line1 = createLabel("\nPlease make sure proportional scaling is disabled", 11, false, NSMakeRect(0, 0, width, 16*2), 0.3);
336 | alert.addAccessoryView(note_line1);
337 |
338 | var responseCode = alert.runModal();
339 |
340 | if(responseCode == 1000){
341 | myresponse.code = 1000
342 | // OK
343 | // pass minmax input
344 | if(minInput.stringValue() == ""){
345 | myresponse.min = myMinMax[0]
346 | }else{
347 | myresponse.min = parseInt(minInput.stringValue())
348 | }
349 | if(maxInput.stringValue() == ""){
350 | myresponse.max = myMinMax[1]
351 | }else{
352 | myresponse.max = parseInt(maxInput.stringValue())
353 | }
354 |
355 | // Force bar chart type
356 | var forcetype_index = matrixFormat_bartype.cells().indexOfObject(matrixFormat_bartype.selectedCell());
357 | myresponse.forcetype = forcetype_index == 0 ? false : true;
358 | }else{
359 | // Cancel
360 | myresponse.code = 1001
361 | }
362 | myresponse.trendTypeInput = matrixFormat.cells().indexOfObject(matrixFormat.selectedCell())
363 | }
364 | return myresponse
365 | }
366 |
367 |
368 |
369 |
370 |
371 |
372 |
373 |
--------------------------------------------------------------------------------
/src/cliptexttosymbol.js:
--------------------------------------------------------------------------------
1 | import sketch from 'sketch'
2 | import { onlyUnique, iterativeGapFilling, createLabel, createDropdown, createCheckbox } from "./utils.js";
3 | // documentation: https://developer.sketchapp.com/reference/api/
4 | // https://github.com/sonburn/symbol-instance-locator/blob/master/Symbol%20Instance%20Locator.sketchplugin/Contents/Sketch/script.js
5 |
6 | var symbolOverrideLayers;
7 |
8 | export default function() {
9 | log('~~ Run Chippen charts ~~')
10 |
11 | const doc = sketch.getSelectedDocument()
12 | const selectedLayers = doc.selectedLayers
13 |
14 | var pluginName = __command.pluginBundle().name();
15 |
16 | if(selectedLayers.layers.length == 0) {
17 | sketch.UI.alert(pluginName,'Please select at least 1 layer that contains a symbol override.');
18 |
19 | return false;
20 | }
21 |
22 |
23 | /*
24 | CLIPBOARD
25 | */
26 |
27 | var newLineSeparator = "\n";
28 | var sep = newLineSeparator;
29 |
30 | var pasteBoard = NSPasteboard.generalPasteboard();
31 | // Turn a data in the string type
32 | var stringFromPasteBoard = pasteBoard.stringForType(NSPasteboardTypeString);
33 |
34 | if(stringFromPasteBoard == null){
35 | sketch.UI.alert(pluginName,'Your clipboard does not seem to be just text. Try again with only lines of text.');
36 | return false;
37 | }
38 |
39 | var pasteboardLines = stringFromPasteBoard.split(newLineSeparator)
40 |
41 |
42 | /*
43 | SELECTED SYMBOLS
44 | */
45 |
46 | const selectedSymbols = selectedLayers.layers.filter(layer => layer.type == "SymbolInstance" || layer.type == "SymbolMaster")
47 | if (selectedSymbols.length == 0) {
48 | sketch.UI.alert(pluginName,'Please select at least 1 layer that contains a symbol.');
49 | return false;
50 | }
51 |
52 | const symbolsWithOverrides = selectedSymbols.filter(symbol => symbol.overrides.length != 0)
53 | if (symbolsWithOverrides.length == 0) {
54 | sketch.UI.alert(pluginName,'Please select at least 1 symbol that contains a text override.');
55 | return false;
56 | }
57 |
58 | const symbolsIDs = symbolsWithOverrides.map(symbol => {
59 | return symbol.symbolId
60 | })
61 |
62 | const uniqueSymbolIDs = symbolsIDs.filter( onlyUnique );
63 |
64 | if(uniqueSymbolIDs.length > 1){
65 | sketch.UI.alert(pluginName,`Please use only symbols of the same kind. Maybe you want to try to use only symbols like "${symbolsWithOverrides[0].name}".`);
66 | return false;
67 | }
68 |
69 |
70 | /*
71 | Informative Text
72 | */
73 |
74 | var warningMsg = ""
75 | if(pasteboardLines.length > symbolsWithOverrides.length){
76 | warningMsg = `There are more lines of text in the clipboard (${pasteboardLines.length}) than there are symbols in the selection (${symbolsWithOverrides.length}). That means not all content from clipboard will be used.`
77 | }else if(symbolsWithOverrides.length > pasteboardLines.length){
78 | warningMsg = `There are more symbols selected (${symbolsWithOverrides.length}) than there are lines of text in the clipboard (${pasteboardLines.length}). Clipboard text will be repeated in the overflow symbols.`
79 | }
80 |
81 | var informativeText = ""
82 | if(warningMsg != ""){
83 | informativeText = "⚠️ Watch out! - " + warningMsg + " \n\nYou can go ahead but outcomes might not be as expected."
84 | }else{
85 | informativeText = `You are about to alter ${symbolsWithOverrides.length} symbol overrides using text from the clipboard.`
86 | }
87 |
88 |
89 | /*
90 | Dropdown options
91 | */
92 |
93 | const stringvalueOverrides = symbolsWithOverrides[0].overrides.filter(override => override.property == 'stringValue')
94 |
95 | const overrideOptions = stringvalueOverrides.map((override, index) => {
96 | return "Override " + (parseInt(index)+1) + " (" + override.value + ")"
97 | })
98 |
99 |
100 | /*
101 | Setup the window
102 | */
103 |
104 | var alert = COSAlertWindow.new()
105 | alert.setMessageText("Paste clipboard text into symbol overrides")
106 | alert.addButtonWithTitle("Run")
107 | alert.addButtonWithTitle("Cancel")
108 | alert.setInformativeText(informativeText)
109 |
110 |
111 | /*
112 | Input
113 | */
114 |
115 | // OVERRIDE DROPDOWN
116 | var alert_width = 280;
117 | var overrideOptions_label = createLabel("What override shall it be? ", 12, true, NSMakeRect(0, 0, alert_width, 16));
118 | var overrideOptions_dropdown = createDropdown(overrideOptions, NSMakeRect(-2, -1, 280, 24));
119 |
120 | if(overrideOptions.length>1){
121 | alert.addAccessoryView(overrideOptions_label);
122 | alert.addAccessoryView(overrideOptions_dropdown);
123 | }
124 |
125 | // REVERSE CHECKBOX
126 | var reverse_checkbox = createCheckbox("Reverse order of clipboard text", false, NSMakeRect(-2, -1, 280, 24));
127 |
128 | if(pasteboardLines.length>1){
129 | alert.addAccessoryView(reverse_checkbox);
130 | }
131 |
132 |
133 | /*
134 | Response
135 | */
136 |
137 | var overrideIndex;
138 | var responseCode = alert.runModal();
139 |
140 | if(responseCode == 1000){
141 | // Dropdown input
142 | var dropddownIndex = overrideOptions_dropdown.indexOfSelectedItem();
143 | var overrideID = stringvalueOverrides[dropddownIndex].id;
144 |
145 | // Mapping index of dropdown to index of overrides.
146 | // Dropdown does only include stringValue overrides
147 | // and no symbolID overrides (top level of nested symbol).
148 | // That's why the length can differ.
149 | for(var i=0; i clip.length){
176 | var clip_filled = iterativeGapFilling(clip, symbolsWithOverrides.length)
177 | clip = clip_filled;
178 | }
179 |
180 | for(var i=0; i= 0){
69 | baseLine = selectedLayers.layers[0].frame.x
70 | }else if(firstBarVal < 0){
71 | baseLine = selectedLayers.layers[0].frame.x + Math.abs(firstBarVal)
72 | }
73 | }
74 |
75 | for(var i = 0; i 0){
106 | // Reposition bars with positive values
107 | selectedLayers.layers[i].frame.y = baseLine - Math.abs(newLength);
108 | }else{
109 | // Reposition bars with negative values
110 | selectedLayers.layers[i].frame.y = baseLine;
111 | }
112 | }else{
113 | // Reset position, just in case
114 | selectedLayers.layers[i].frame.x = baseLine;
115 |
116 | // Change width
117 | selectedLayers.layers[i].frame.width = Math.abs(newLength);
118 |
119 | // Reposition bars with negative values
120 | if(newLength < 0){
121 | selectedLayers.layers[i].frame.x = selectedLayers.layers[i].frame.x - Math.abs(newLength)
122 | }
123 | }
124 |
125 | // Rename layer
126 | // Data value will be added to layer name
127 | // Example: Rectangle ==> Rectangle {:12:}
128 | selectedLayers.layers[i].name = renameLayer(selectedLayers.layers[i].name, response.numbers[i])
129 | }
130 |
131 | // Notification
132 | // Alert in case number of selected layers
133 | // does not match amount of numbers
134 | if(alert_diff != 0){
135 | if(alert_diff > 0){
136 | sketch.UI.alert(`😇 Just letting you know`, `Only the first ${response.numbers.length} of your selected layer(s) have been adjusted. There weren't enough number values to adjust the last ${Math.abs(alert_diff)} layer(s). Maybe check the separator options (comma, etc).`);
137 | }else if(alert_diff < 0){
138 | sketch.UI.alert(`😇 Just letting you know`, `The last ${Math.abs(alert_diff)} values weren't used as there weren't enough layer(s) selected.`)
139 | }
140 | }
141 | }
142 |
143 | function getMinMax(arr, isVertical){
144 | // arr needs to be doc.selectedLayers
145 | var min = 0;
146 | var max = 0;
147 |
148 | if(isVertical){
149 | // Vertical bar chart (get minMax height)
150 | for(var i = 0; imax){
154 | max = thisHeight
155 | }
156 | // Min
157 | if(min == 0){
158 | // set min at first runfirst
159 | min = max
160 | }
161 | if(thisHeight < min){
162 | min = thisHeight
163 | }
164 | }
165 | }else{
166 | // Horizontal bar chart (get minMax width)
167 | for(var i = 0; i max){
171 | max = thisWidth
172 | }
173 | // Min
174 | if(min == 0){
175 | // set min at first run
176 | min = max
177 | }
178 | if(thisWidth < min){
179 | min = thisWidth
180 | }
181 | }
182 | }
183 |
184 | return [Math.ceil(min), Math.ceil(max)]
185 | }
186 |
187 | function myinput(myMinMax=[20,100], numOfBars="", myBarHeightFromSelection, my_isVertical){
188 | var myresponse = {
189 | code: null,
190 | max: null,
191 | forcetype : false,
192 | numbers: [],
193 | trendTypeInput: null
194 | }
195 |
196 | if(myMinMax.length != 2 || myMinMax[0]==myMinMax[1]){
197 | if(myMinMax[0] > 100){
198 | myMinMax = [20,myMinMax[1]]
199 | }else{
200 | myMinMax = [myMinMax[0],100]
201 | }
202 |
203 | }
204 |
205 | if(numOfBars==0){
206 | myresponse.code == 1001
207 | sketch.UI.alert("Sorry buddy", "You need to select multiple rectangles (bars) for this plugin to work.")
208 | }
209 | if(numOfBars!=0){
210 |
211 | if(numOfBars==1){
212 | sketch.UI.alert("Hey, just letting you know", "Most awesome results come when selecting more than 1 bar.")
213 | }
214 |
215 | // Create initial view panel
216 | var width = 260
217 | var height = 40
218 |
219 | // Number input
220 | var sampleNumbers = myBarHeightFromSelection;
221 |
222 | /*
223 | Setup the window
224 | */
225 |
226 | var alert = COSAlertWindow.new()
227 | if(numOfBars==1){
228 | alert.setMessageText("1 layer selected to create bar chart")
229 | }else{
230 | alert.setMessageText(`${numOfBars} layers selected to create bar chart`)
231 | }
232 | alert.addButtonWithTitle("Run")
233 | alert.addButtonWithTitle("Cancel")
234 | alert.setInformativeText(`This is for a bar chart with specific values, rather than random numbers.`)
235 |
236 | /*
237 | Input
238 | */
239 | var alert_width = 280;
240 | var numInput_separatorOptions = [
241 | "Comma separated",
242 | "Space separated",
243 | "Tab separated (Excel row)",
244 | "Line break separated (Excel column)",
245 | ]
246 |
247 | var numInput_label = createLabel("Paste in your number values", 12, true, NSMakeRect(0, 0, alert_width, 16));
248 | var numInput = createTextField(sampleNumbers, null, NSMakeRect(0, 0, alert_width, 25));
249 | var numInput_separator = createDropdown([
250 | numInput_separatorOptions[0],
251 | numInput_separatorOptions[1],
252 | numInput_separatorOptions[2],
253 | numInput_separatorOptions[3]
254 | ], NSMakeRect(-2, -1, 170, 30));
255 | alert.addAccessoryView(numInput_label);
256 | alert.addAccessoryView(numInput);
257 | alert.addAccessoryView(numInput_separator);
258 |
259 |
260 | /*
261 | Bar type: Vertical or horizontal
262 | */
263 |
264 | var bartype_label = createLabel("Vertical or horizontal?", 12, true, NSMakeRect(0, 0, alert_width, 16));
265 | alert.addAccessoryView(bartype_label);
266 |
267 | var bartype_radio = NSView.alloc().initWithFrame(NSMakeRect(0, 0, width, 48))
268 | var buttonFormat;
269 | buttonFormat = NSButtonCell.alloc().init();
270 | buttonFormat.setButtonType(NSRadioButton);
271 |
272 | var matrixFormat = NSMatrix.alloc().initWithFrame_mode_prototype_numberOfRows_numberOfColumns(
273 | NSMakeRect(0, 0, 260, 48),
274 | NSRadioModeMatrix,
275 | buttonFormat, 2, 1
276 | );
277 |
278 | matrixFormat.setCellSize(CGSizeMake(260, 25));
279 |
280 | var bartype_radio1_label = my_isVertical ? "Automatic (vertical detected)" : "Automatic (horizontal detected)"
281 | var bartype_radio2_label = my_isVertical ? "Force horizontal" : "Force vertical"
282 | var cells = matrixFormat.cells();
283 | cells.objectAtIndex(0).setTitle(bartype_radio1_label);
284 | cells.objectAtIndex(1).setTitle(bartype_radio2_label);
285 |
286 | bartype_radio.addSubview(matrixFormat);
287 | alert.addAccessoryView(bartype_radio)
288 |
289 |
290 | /*
291 | Options
292 | */
293 | var optionsView_height = 85;
294 |
295 | var optionsView = NSView.alloc().initWithFrame(NSMakeRect(0, 0, alert_width, optionsView_height));
296 | var optionsLabel = createLabel("Do you want to scale the values?", 12, true, NSMakeRect(0, optionsView_height - 26, alert_width, 16));
297 | //var optionsLabel_inlineNote = createLabel("(optional)", 12, false, NSMakeRect(215, optionsView_height - 26, alert_width, 16), 0.3);
298 |
299 | var option1_textField = createTextField("", "e.g. 1.5", NSMakeRect(0, optionsView_height-60, 120, 25));
300 | var option1_label = createLabel("Multiply by", 12, false, NSMakeRect(0, optionsView_height-79, 130, 16));
301 |
302 | var option2_textField = createTextField("", "e.g. " + 100, NSMakeRect(140, optionsView_height-60, 120, 25)); // prev version showed myMinMax[1] as option
303 | var option2_label = createLabel("or set max height (px)", 12, false, NSMakeRect(140, optionsView_height-79, 130, 16));
304 |
305 | //var options_info = createLabel("You have the option to define the scaling in case the supplied values don't match your desired pixel values. You can either define a multiplier or set a maximum bar height in pixel.", 11, false, NSMakeRect(0, 0, 260, 16*4))
306 | var options_info = createLabel("Scale data values in case the supplied numbers don't match the desired pixel values.", 11, false, NSMakeRect(0, 0, 260, 16*2))
307 |
308 | optionsView.addSubview(optionsLabel);
309 | //optionsView.addSubview(optionsLabel_inlineNote);
310 |
311 | optionsView.addSubview(option1_textField);
312 | optionsView.addSubview(option1_label);
313 |
314 | optionsView.addSubview(option2_textField);
315 | optionsView.addSubview(option2_label);
316 |
317 | alert.addAccessoryView(optionsView);
318 | // alert.addAccessoryView(options_info)
319 |
320 |
321 | /*
322 | Key navigation (popup)
323 | */
324 |
325 | alert.alert().window().setInitialFirstResponder(numInput);
326 | numInput.setNextKeyView(option1_textField)
327 | option1_textField.setNextKeyView(option2_textField)
328 | option2_textField.setNextKeyView(numInput)
329 |
330 |
331 | /*
332 | Note
333 | */
334 |
335 | var note_line1 = createLabel("Please make sure proportional scaling is disabled", 11, false, NSMakeRect(0, 0, alert_width+10, 16), 0.3);
336 | alert.addAccessoryView(note_line1);
337 |
338 |
339 | /*
340 | RESPONSE
341 | */
342 |
343 | var responseCode = alert.runModal();
344 |
345 | if(responseCode == 1000){
346 | myresponse.code = 1000
347 | // OK
348 |
349 | // Separator
350 | var sep = ","
351 | var sep_input = numInput_separator.titleOfSelectedItem()
352 | if(sep_input == numInput_separatorOptions[1]){
353 | sep = " "
354 | }if(sep_input == numInput_separatorOptions[2]){
355 | sep = "\t"
356 | }else if(sep_input == numInput_separatorOptions[3]){
357 | sep = "\n"
358 | }
359 |
360 | // Numbers
361 | var numbers_str = "";
362 | if(numInput.stringValue() == ""){
363 | numbers_str = sampleNumbers
364 | }else{
365 | numbers_str = numInput.stringValue();
366 | }
367 | var numbers_arr = numbers_str.split(sep)
368 | for(var i=0; i=0 ? -1 : 1;
109 |
110 | var new_add = Math.abs(new_diff) / (num_of_colours-1);
111 | var new_dim = col1_rgb[j] + new_dir*(i+1)*new_add;
112 |
113 | new_rgb.push(Math.round(new_dim))
114 | }
115 | colours.push(rgbToHex(new_rgb))
116 | }
117 |
118 | colours.push(col2) // last colour
119 |
120 |
121 | // Apply new colours to selection
122 | for(var i = 0; i d8d8d8
154 | return hex.substr(1,6);
155 | }
156 |
157 | function hex_9 (hex_6){
158 | // d8d8d8 > #d8d8d8ff
159 | return "#" + hex_6 + "ff";
160 | }
161 |
162 | function rgbToHex(arr){
163 | var hex = "";
164 | for(var i=0; i<3; i++){
165 | var sub = arr[i].toString(16).toUpperCase();
166 | var padsub = ('0'+sub).slice(-2);
167 | hex = hex + padsub
168 | }
169 | return hex;
170 | }
171 |
172 | function removeHash(hex){
173 | return hex.substr(0,1)=="#" ? hex.substr(1,6) : hex;
174 |
175 | }
--------------------------------------------------------------------------------
/src/utils.js:
--------------------------------------------------------------------------------
1 | export function getSymbolInstances(source,symbolMaster) {
2 | // https://github.com/sonburn/
3 | var symbolInstances = NSMutableArray.array();
4 |
5 | source.sketchObject.pages().forEach(function(page){
6 | var predicate = NSPredicate.predicateWithFormat('className == %@ && symbolMaster.objectID == %@','MSSymbolInstance',symbolMaster.sketchObject.objectID());
7 |
8 | page.children().filteredArrayUsingPredicate(predicate).forEach(instance => symbolInstances.addObject(instance));
9 | });
10 |
11 | return symbolInstances;
12 | }
13 |
14 | export function onlyUnique(value, index, self) {
15 | return self.indexOf(value) === index;
16 | }
17 |
18 | export function iterativeGapFilling(array, length){
19 | var newArray = [];
20 | for(var i=0; i 1){
102 | var b = a[1].split(":}");
103 | if(b.length == 1){return newName;}
104 | var newName = a[0] + "{:" + newVal + ":}" + b[1];
105 | }
106 |
107 | return newName
108 | }
109 |
110 |
111 | /**********************/
112 | /* BARCHART */
113 | /**********************/
114 |
115 | export function isVerticalBarchart(arr){
116 | // arr needs to be doc.selectedLayers
117 | var isVertical = true
118 | if(arr.layers.length >= 2 && arr.layers[0].frame.y != arr.layers[1].frame.y){
119 | // It's horizontal if
120 | // 1. First two bars share same x value (works for positive values)
121 | if(arr.layers[0].frame.x == arr.layers[1].frame.x){
122 | isVertical = false;
123 | }
124 | // 2. Same y-baseline (works if first value is negative)
125 | // and they share same height
126 | // ! Needs check if first / second val is negative
127 | else if(arr.layers[0].frame.x + arr.layers[0].frame.width == arr.layers[1].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){
128 | isVertical = false;
129 | }
130 | else if(arr.layers[1].frame.x + arr.layers[1].frame.width == arr.layers[0].frame.x && arr.layers[0].frame.height == arr.layers[1].frame.height){
131 | isVertical = false;
132 | }
133 | }
134 | return isVertical
135 | }
136 |
137 |
138 | /**********************/
139 | /* NON-RANDO BARCHART */
140 | /**********************/
141 |
142 | export function getBarHeight(arr, isVertical){
143 | // arr needs to be doc.selectedLayers
144 | var barLength_str = ""
145 |
146 | for(var i=0; i