Skip to content

Instantly share code, notes, and snippets.

@gerrit
Created August 25, 2015 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gerrit/67896785094a6ba016fe to your computer and use it in GitHub Desktop.
Save gerrit/67896785094a6ba016fe to your computer and use it in GitHub Desktop.
Sketch Plugin API questions
## Reordering layers
I'm working on a command that creates a rectangle in the background of a text layer (with slightly larger dimensions than the text). For that, I need to manipulate the generated layer's z-order, but couldn’t find anything to that extent in the docs. `group.layers()`, as an `MSArray`, also doesn’t expose methods that could do the trick such as `exchangeObjectWithIndex:withIndex:`.
As a workaround I'm using a [technique lifted from sketch-style-inventory][INV]: calculating the offset of two layers and then doing a bunch of `NSApp.sendAction_to_from('moveForward:', nil, context.doc);` calls. But that seems hacky at best, feels like there should be a proper API for the common usecase of wanting to manipulate z-order of layers (or is there an undocumented way?).
## Expanding frames
The [MSRect docs][MSRECT] have a code example for `expandBy:` that I tried to emulate, but failed, that method doesn’t seem to exist on either `MSRect` or `GKRect`:
```
var rect = parent.addLayerOfType('rectangle');
// TypeError: undefined is not a function (evaluating 'rect.absoluteRect().expandBy(2.0)')
rect.absoluteRect().expandBy(2.0);
// TypeError: undefined is not a function (evaluating 'rect.frame().expandBy(2.0)')
rect.frame().expandBy(2.0);
```
My workaround is this:
```
function expandLayerBy(layer, extentX, extentY) {
var frame = layer.frame();
// HACK: these are deprecated, in favor of layer.rect()
// but couldn’t get it to work with that
frame.addWidth(extentX);
frame.addHeight(extentY);
frame.subtractX(extentX/2);
frame.subtractY(extentY/2);
}
```
This works, but complains about deprecation in the console: `WARNING: Direct interaction with MSRect is discouraged, and subtractX: is deprecated. Please use rect/setRect on MSLayer instead`
But the (undocumented) `rect()` returns a `CGRect` struct, doing simple mutations for things like changing the width of a layer with that is non-obvious (for non-cocoaheads like myself at least). Is one supposed to create and assign a new CGRect witht he right parameters by hand? [Apple's docs][CG] say "your applications should avoid directly reading and writing the data stored in the CGRect data structure" so to me it seems a bit surprising to me to be exposing this in the plugin API.
## Copying frames
`MSLayer#frame()` is marked as readonly in the [MSLayer docs][MSLAYER] but doing a `layer2.frame = layer1.frame()` in code *seems* to work, but leads to some… *interesting* drawing bugs/artifacts down the road (they even persist in the doc across restarts of sketch). I'm assuming this is because the assignment leads to are two layers referencing a single frame instance rather than having a value struct copyed.
Would be great if that was possible to do though, right now I'm writing a plugin where I have to do a lot of this and the utility function I wrote to get around this isn’t very pretty:
```
function copyFrame(layer1, layer2) {
layer1.frame().setX(layer2.frame().x());
layer1.frame().setY(layer2.frame().y());
layer1.frame().setWidth(layer2.frame().width());
layer1.frame().setHeight(layer2.frame().height());
}
```
[INV]: https://github.com/getflourish/Sketch-Style-Inventory/blob/master/inventory.js#L2322
[MSRECT]: http://bohemiancoding.com/sketch/support/developer/03-reference/MSRect.html
[MSLAYER]: http://bohemiancoding.com/sketch/support/developer/03-reference/MSLayer.html
[CG]: https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CGGeometry/#//apple_ref/c/tdef/CGRect
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment