Skip to content

Commit

Permalink
extended and rewritten for Sketch 3
Browse files Browse the repository at this point in the history
- 'Toggle' automatically determines if the (majority of) matching
layers are currently visible or hidden and toggles their visibility
accordingly

- 'Show' makes all matching layers visible

- 'Hide' makes all matching layers hidden

- 'Settings' allows for the layer name to be changed as desired. '*'
can be used as a wildcard meaning that 'box*' will match 'box', 'box
1', 'box-something', etc. '*' can be used anywhere within the layer
name string.
  • Loading branch information
Lukas Ondrej committed Nov 3, 2015
1 parent 021d0c8 commit c8b5414
Show file tree
Hide file tree
Showing 10 changed files with 314 additions and 0 deletions.
Binary file added Demo.sketch
Binary file not shown.
@@ -0,0 +1,9 @@
//===============================================
// sketch layer visibility - config
//===============================================

var Config = {

//define default layer name
defaultLayerName: "boundingBox*"
}
@@ -0,0 +1,122 @@
//===============================================
// sketch layer visibility - library
//===============================================

var Library = {};
(function(self) {

self.jsArray = jsArray;
self.findLayers = findLayers;
self.createAlert = createAlert;
self.createLabel = createLabel;


//===============================================


function jsArray(array) {
var length = [array count];
var jsArray = [];

while (length--) {
jsArray.push([array objectAtIndex: length]);
}
return jsArray;
}


function findLayers(name, exactMatch, type, rootLayer, subLayersOnly, layersToExclude) {

//create predicate format
var formatRules = ['(name != NULL)'];
var arguments = [];

//name
if(name) {
if(exactMatch) {
formatRules.push('(name == %@)');
}
else {
formatRules.push('(name like %@)');
}
arguments.push(name);
}

//type
if(type) {
formatRules.push('(className == %@)');
arguments.push(type);
}
else {
formatRules.push('(className == "MSLayerGroup" OR className == "MSShapeGroup" OR className == "MSArtboardGroup" OR className == "MSTextLayer")');
}

//layers to exclude
if(layersToExclude) {
formatRules.push('NOT (SELF IN %@)');
arguments.push(layersToExclude);
}

//prepare format string
var formatString = formatRules.join(' AND ');

//create predicate
predicate = [NSPredicate predicateWithFormat: formatString argumentArray: arguments];

//get layers to filter
var layers;
if (subLayersOnly) {
layers = [[rootLayer layers] array];
} else {
layers = [rootLayer children];
}

//perform query
var queryResult = [layers filteredArrayUsingPredicate: predicate];

//return result as js array
return jsArray(queryResult);
}


function createAlert(title, message, iconFileName) {

var alert = [COSAlertWindow new];
[alert setMessageText: title];
[alert setInformativeText: message];

if(iconFileName) {

//get icon path
var scriptPath = [NSString stringWithString: context.scriptPath];
scriptPath = [scriptPath stringByDeletingLastPathComponent];
var iconPath = [scriptPath stringByAppendingPathComponent: iconFileName];

//set icon
var icon = [[NSImage alloc] initByReferencingFile: iconPath];
[alert setIcon: icon];
}

return alert;
}


function createLabel(text, fontSize, bold, frame) {

var label = [[NSTextField alloc] initWithFrame:frame];
[label setStringValue:text];
if(bold) {
[label setFont:[NSFont boldSystemFontOfSize:fontSize]];
}
else {
[label setFont:[NSFont systemFontOfSize:fontSize]];
}
[label setBezeled:false];
[label setDrawsBackground:false];
[label setEditable:false];
[label setSelectable:false];

return label;
}

})(Library);
40 changes: 40 additions & 0 deletions Sketch Layer Visibility.sketchplugin/Contents/Sketch/manifest.json
@@ -0,0 +1,40 @@
{
"name": "Sketch Layer Visiblity",
"description": "",
"identifier": "com.precious-forever.sketch.layervisibility",
"version": "1.0",
"commands": [{
"name": "Toggle",
"identifier": "toggleLayers",
"script": "plugin.cocoascript",
"handler": "toggleLayersHandler",
"shortcut": ""
}, {
"name": "Show",
"identifier": "showLayers",
"script": "plugin.cocoascript",
"handler": "showLayersHandler",
"shortcut": ""
}, {
"name": "Hide",
"identifier": "hideLayers",
"script": "plugin.cocoascript",
"handler": "hideLayersHandler",
"shortcut": ""
}, {
"name": "Settings",
"identifier": "settings",
"script": "plugin.cocoascript",
"handler": "settingsHandler",
"shortcut": ""
}],
"menu": {
"isRoot": false,
"items": [
"toggleLayers",
"showLayers",
"hideLayers",
"settings"
],
}
}
@@ -0,0 +1,143 @@
//===============================================
// sketch layer visibility - plugin
//===============================================

@import 'library.cocoascript';
@import 'config.cocoascript';


//store global context reference
var context;


function toggleLayersHandler(_context) {
context = _context;

//toggle
(isShowing()) ? hideLayers() : showLayers();
}


function showLayersHandler(_context) {
context = _context;
showLayers();
}


function hideLayersHandler(_context) {
context = _context;
hideLayers();
}


function settingsHandler(_context) {
context = _context;

//get user defaults
var defaults = [NSUserDefaults standardUserDefaults];

//create alert
var alert = Library.createAlert("Settings", "", "");

//create layer name view
var layerNameView = [[NSView alloc] initWithFrame: NSMakeRect(0, 0, 300, 22)];

//create layer name title
var layerNameTitle = Library.createLabel('Layer name:', 12, false, NSMakeRect(0, 0, 80, 20));
[layerNameView addSubview: layerNameTitle];

//create layer name text field
var layerNameTextField = [[NSTextField alloc] initWithFrame:NSMakeRect(80, 0, 200, 22)];
[layerNameView addSubview: layerNameTextField];

//set current layer name
if(![defaults objectForKey: "layerName"]) setDefaultLayerName();
[layerNameTextField setStringValue: [defaults objectForKey: "layerName"]];

//add layer name view to alert
[alert addAccessoryView: layerNameView];

//add bottom buttons
[alert addButtonWithTitle:"Save"];
[alert addButtonWithTitle:"Cancel"];

//show settings alert
var responseCode = [alert runModal];
if(responseCode == '1000') {

//set new search string
[defaults setObject: [layerNameTextField stringValue] forKey: "layerName"]];
}
}


function showLayers() {

//show layers
findLayers().forEach(function(layer) {

//turn visibility on
layer.setIsVisible(true);
});
}


function hideLayers() {

//hide layers
findLayers().forEach(function(layer) {

//turn visibility off
layer.setIsVisible(false);
});
}


function isShowing() {

//track sum and count
var sum = 0;
var count = 0;

//check each layer
findLayers().forEach(function(layer) {
sum += Number(layer.isVisible());
count++;
});

//if more than half of layers are visible,
//consider the state as showing
return (sum / count > 0.5);
}


function findLayers() {

//get current page
var currentPage = context.document.currentPage();

//get user defaults
var defaults = [NSUserDefaults standardUserDefaults];

//get layer name
if(![defaults objectForKey: "layerName"]) setDefaultLayerName();

//find matching layers
return Library.findLayers([defaults objectForKey: "layerName"], false, false, currentPage, false, null);
}


function setDefaultLayerName() {

//get user defaults
var defaults = [NSUserDefaults standardUserDefaults];

//default default layer name
[defaults setObject: Config.defaultLayerName forKey: "layerName"];

//sync
[defaults synchronize];
}



File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit c8b5414

Please sign in to comment.