Sketch Plugin CookBook (ver.51まで)
Sketch 52でAPIが変更になっているため、動かない記述があります。
忘れやすい自分のための、Sketch.app向けプラグイン開発メモ。
ツギハギで書いてきたため、内容をあまり精査できていません。ところどころ書き換えできずに間違ってます。さらにClass自体が非推奨になった(リファレンスからなくなった)ようで、この書き方は使えなくなる可能性が高いです。「使えなくなる」ではなく、JavaScript API経由で使えってことになりそうです。
Sketchのプラグインは、CocoaScirptで開発する。とてもざっくり言うと、Objective-CをJavaScriptライクに扱う言語(キモイ)。記述はJavaScriptスタイルとObjective-Cスタイルがあり、混在もOK。
ドキュメントとか参考情報
クラスリファレンスが見たい場合は、こちらのコミットからローカルへクローンしてJekyllでビルドすれば復元できます。
フォーラム
メーリングリストとそのアーカイブ
こちらも参考に
- Sketch Pluginの開発(開発編) - Qiita
- Sketch Pluginの開発(前提知識編) - Qiita
- SketchのiOS UI Design Templateを🈲で埋め尽くすプラグイン - Qiita
- アプリ用画像アセットを書き出す Sketch Plugin を作ってみた話 - Re.Ra.Ku アドベントカレンダー day 6 - Re.Ra.Ku tech blog
- Sketch3のプラグインを開発する - Qiita
- Sketch Plugin についての要約とメモ。あるいは Sketch Plugin の始め方。 - Qiita
- Sketch-Plugins-Cookbook
- Sketch Plugin Snippets for Plugin Developers — Design + Sketch App — Medium
- CocoaScript(CocoaScriptのサンプル)
デバッグ
公式ドキュメント:Debugging — Sketch Developer
公式ドキュメントではフィルタの設定を「sketch」としているが、プラグインのメッセージだけをみたいのであれば、「sketch plugin」とした方が良い、と思う。
Class Dump
class-dumpというコマンドラインツールをインストールすると、メソッドやプロパティを調べることができる。Class-dumpの配布ページからファイルをダウンロードし、中にあるclass-dump
を/usr/local/bin
あたりへコピーする。
$ cp /Volumes/class-dump-3.5/class-dump /usr/local/bin/class-dump
ターミナルで次のコマンドを叩けば、プロパディやメソッドを取得できる。
# 含まれるフレームワークすべて
$ class-dump /Applications/Sketch.app
# フレームワークを指定
$ class-dump /Applications/Sketch.app/Contents/Frameworks/CocoaScript.framework
# ファイルとしてホームディレクトリへ書き出す場合
$ class-dump /Applications/Sketch.app > ~/sketch-class-dump.txt
参考記事でも紹介されていたSketch Headersで、同様の情報が閲覧できますので、お好きな方で。
オブジェクトの構成を出力するtreeAsDictionary()
オブジェクトの構造はtreeAsDictionary()
を使うとログに吐き出すことができ、プロパティ名からメソッドを憶測できる。
// 選択しているシェイプの構造をログで出力
var sel = context.selection;
var shape = sel[0];
log( shape.frame().treeAsDictionary() );
これを実行すると、次の出力を得ることができる。
{
"<class>" = MSRect;
constrainProportions = 0;
height = 159;
width = 145;
x = 179;
y = 169;
}
クラスやインスタンスが持つメソッドを出力するinstanceMethods()
とclassMethods()
また、class-dumpを紹介したものの、instanceMethods()
やclassMethods()
を使うと、そのクラスが持っているメソッドを吐き出すこともできる。
// 選択しているシェイプの構造をログで出力
var sel = context.selection;
var shape = sel[0];
log( shape.frame().class().mocha().instanceMethods() );
これを実行すると、次の出力を得ることができる(
(
"<MOMethodDescription: 0x6100004266c0 : selector=makeOriginIntegral, typeEncoding=v16@0:8>",
"<MOMethodDescription: 0x610000426700 : selector=makeRectIntegral, typeEncoding=v16@0:8>",
// 長いため中略
"<MOMethodDescription: 0x610000428260 : selector=setOrigin:, typeEncoding=v32@0:8{CGPoint=dd}16>",
"<MOMethodDescription: 0x610000428300 : selector=setRect:, typeEncoding=v48@0:8{CGRect={CGPoint=dd}{CGSize=dd}}16>"
)
ちなみにclassMethods()
のものはnew()
しなくても使える。
プロパティを出力するproperties()
// プロパティのダンプ
var sel = context.selection;
var shape = sel[0];
log( shape.frame().class().mocha().properties() );
Atom向けのプラグイン実行パッケージ
Atomから直接Sketchプラグインを実行できるパッケージ。パッケージマネージャなどでインストールしCommand + R
すると、定義されてているメソッドをパレットから選択して実行できる。
ちなみにAutherはContent Generator Pluginの人。
プラグインの構造
PLUGINNAME.sketchplugin
└ Contents
└ Sketch
├ SCRIPT.sketchscript
└ manifest.json
Pluginsメニューへの表示はmanifest.json
で管理するため、SCRIPT.sketchscript
は複数あっても良い。拡張子も.js
や.cocoascript
でも大丈夫。ライブラリなどはSketchディレクトリ内にさらにディレクトリを作成し、その中に突っ込んでもOK。外部のスクリプトを読み込むには、@import
を使ってファイルの先頭へ次のように書く。
@import 'lib/script.js';
旧形式のプラグインについて
以前はディレクトリへ実行ファイルのそのものである.sketchplugin
を突っ込んでおけば良かったが、3.3から形式が変更になっている。3.4からPreferencesへプラグインマネージャーが実装され、manifest.json
がないと「Legacy Plugins」として1つにまとめられてプラグインを管理できなくなるので注意。
この旧形式でも41現在、きちんとメンテナンスされていれば実行は可能だが、Legacy PluginはPluginsメニューの別メニューにまとめられてしまう。今後、いつ使えなくなるかわからないため、よく使うプラグインが旧形式なら要注意。
こちらを参照:Plugin News — Sketch Developer
manifest.json
manifest.jsonは、Pluginsメニューやプラグインマネージャーで表示する内容を設定するファイル。下記は、拙作「Sketch CSS Sprite Mixin」のファイルの一部を抽出。こちらはがんばって書いている感じなので、最低限の記述は「Sketch3のプラグインを開発する」を参照のこと。
{
"author": "littlebusters", // プラグインマネージャーで表示
"menu" : {
"isRoot" : false, // Pluginsメニュー直下へ表示するかどうか
"shortcut" : "",
"items" : [ // メニュー上の並びを設定。commands[INDEX].identifierを指定する。3.3では無効
"css-sprite-mixin-scss",
"css-sprite-mixin-sass",
"css-sprite-mixin-less",
"-", // 3.4.1より、ハイフンを入れるとセパレータとして表示されるように
"css-sprite-mixin-stylus"
],
"title" : "Sketch CSS Sprite Mixin" // Pluginsメニューでのフォルダ名
},
"identifier": "net.creative-tweet.css-sprite-mixin",
"version": "1.1.0", // プラグインマネージャーで表示
"description" : "Generate a code of CSS Sprite Mixin to Clipboard in Sketch.", // プラグインマネージャーで表示
"name" : "Sketch CSS Sprite Mixin", // プラグインマネージャー上の名前。指定しない場合は、ファイル名から取得される
"commands" : [
{
"name": "Scss", // Pluginsメニュー上の表示
"identifier": "css-sprite-mixin-scss",
"handler" : "getScss", // 下のscript内にあるメソッドを指定
"script": "css-sprite-mixin.sketchscript" // スクリプトファイルを指定
}
]
}
Global Variable
メソッドにcontext
という引数を渡して実行してやる。旧形式でいうdoc
や選択しているレイヤーを取得するには次の通り。
var onRun = function(context) {
var doc = context.document;
var sel = context.selection;
}
サンプルコード
doc
となっているところは、事前にvar doc = context.document;
となっている前提とするか、context.document
と読み替えてください。
非推奨になっているmethod
- MSArray.length() -> MSArray.count() // 3.8
- setPatternImage() -> SetImage() // 3.8
- addLayerOfType() -> それぞれのクラスからインスタンスを作成する // 3.8
- convertToSymbol() -> convertArtboardToSymbol() // 41
- MSColor -> MSImmutableColor // 41
バージョンの取り方
Bohemian Coding的には最新版しかサポートしない感じですが、とりあえずバージョンによる分岐をする場合に必要なバージョンの取得方法。ちなみに、3.8の次は3.9かと思ったら39になってしまったので、39以降はmajor
には二桁の数字が入ります。
var appVer = {}
appVer.full = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
appVer.major = ( appVer.full.split( '.' ) )[0];
appVer.minor = ( appVer.full.split( '.' ) )[1] || 0;
appVer.revision = ( appVer.full.split( '.' ) )[2] || 0;
ページ関連
参考
現在のページを取得
// JS Style
var doc = context.document;
var currentPage = doc.currentPage();
// Obj-c style
var doc = context.document;
var currentPage = [doc currentPage];
ドキュメント内のページ数
// JS Style
var doc = context.document;
var docPages = doc.pages();
log( docPages.count() ); // ページ数を表示
// Obj-c style
var doc = context.document;
var docPages = [doc pages];
log( [docPages count] ); // ページ数を表示
新しいページを追加
// JS Style
var doc = context.document;
doc.addBlankPage();
// Obj-c style
var doc = context.document;
[doc addBlankPage];
現在のページ名を取得
// JS Style
var doc = context.document;
var currentPage = doc.currentPage();
log( currentPage.name() );
// Obj-c style
var doc = context.document;
var currentPage = [doc currentPage];
log( [currentPage name] );
現在のページ名を変更
// JS Style
var doc = context.document;
var currentPage = doc.currentPage();
currentPage.setName( 'Page Name' );
// Obj-c style
var doc = context.document;
var currentPage = doc.currentPage();
[[currentPage] setName:'Page Name'];
アートボード関連
アートボードの一覧を取得
// JS Style
var doc = context.document;
var artboards = doc.currentPage().artboards();
if ( 0 < artboards.count() ) {
for ( var i = 0; i < artboards.count(); i++ ) {
log( artboards[i].name() );
log( artboards[i].frame().width() );
log( artboards[i].frame().height() );
log( artboards[i].frame().x() );
log( artboards[i].frame().y() );
}
}
// Obj-c style
var doc = context.document;
var artboards = [[doc currentPage] artboards];
if ( 0 < [artboards count] ) {
for ( var i = 0; i < [artboards count]; i++ ) {
log( [[artboards objectAtIndex:i] name] );
log( [[[artboards objectAtIndex:i] frame] width] );
log( [[[artboards objectAtIndex:i] frame] height] );
log( [[[artboards objectAtIndex:i] frame] x] );
log( [[[artboards objectAtIndex:i] frame] y] );
}
}
現在のアートボードを取得
// JS Style
var doc = context.document;
var currentArtboard = doc.currentPage().currentArtboard();
if ( 0 > currentArtboard.count() ) {
log( currentArtboard.name() );
}
// Obj-c style
var doc = context.document;
var artboard = [[doc currentPage] currentArtboard];
if ( 0 < [artboards count] ) {
log( [currentArtboard name] );
}
アートボードを作成
// JS Style
var doc = context.document;
var artboard = MSArtboardGroup.new();
artboard.setName( 'Artboard Name' );
artboard.frame().setX( 0 );
artboard.frame().setY( 0 );
artboard.frame().setWidth( 480 );
artboard.frame().setHeight( 720 );
doc.addLayer( artboard );
// Obj-c style
var doc = context.document;
var artboard = [MSArtboardGroup new];
[artboard setName: 'Artboard Name'];
[[artboard frame] setX: 0];
[[artboard frame] setY: 0];
[[artboard frame] setWidth: 480];
[[artboard frame] setHeight: 720];
[doc addLayer: artboard];
複数のアートボードを追加する場合は、doc.addLayer()
の部分を次のように変更する。
// JS Style
var currentPage = doc.currentPage();
currentPage.addLayers( NSArray.arrayWithObjects( artboard ) );
// Obj-c Style
var currentPage = [doc currentPage];
[currentPage addLayers:[NSArray arrayWithObjects: artboard]];
現在のアートボードへガイドラインを追加する
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var vRuler = artboard.verticalRulerData();
var hRuler = artboard.horizontalRulerData();
vRuler.addGuideWithValue( 100 ); // 垂直
hRuler.addGuideWithValue( 100 ); // 水平
現在のアートボードのグリッドを設定する
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var grid = MSSimpleGrid.new();
grid.setGridSize( 16 );
artboard.grid = grid;
レイヤーの作成と設定
グループの作成
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var group = MSLayerGroup.new();
group.setName( 'Group Name' );
artboard.addLayers( [group] );
矩形(Rectangle)を作成
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var rectangle = MSRectangleShape.new();
rectangle.name = 'Layer Name';
rectangle.frame().x = 0;
rectangle.frame().y = 0;
rectangle.frame().width = 100;
rectangle.frame().height = 150;
var shape = MSShapeGroup.shapeWithPath( rectangle );
artboard.addLayers( [shape] );
ベジェを作成
参考
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var bezierPath = NSBezierPath.bezierPath();
bezierPath.moveToPoint( NSMakePoint( 0, 0 ) ); // パスを開始する座標
// 直線を引く
bezierPath.lineToPoint( NSMakePoint( 50, 50 ) ); // アンカーポイントの座標
// 曲線を引く
var ancher = NSMakePoint( 200, 200 ); // アンカーポイントの座標
var currentHandle = NSMakePoint( 150, 200 ); // 作成するアンカーポイントのハンドルの座標
var prevHandle = NSMakePoint( 50, 100 ); // 元のアンカーポイントのハンドルの座標
// 曲線を生成
[bezierPath curveToPoint:ancher controlPoint1:prevHandle controlPoint2:currentHandle];
// パスを閉じる
bezierLine.closePath();
var shape = MSShapeGroup.shapeWithBezierPath( bezierPath );
artboard.addLayers( [shape] ); // ベジェシェイプをアートボードへ追加
マスクの作成
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
// マスクの影響を抑える為にグループを作成
var group = MSLayerGroup.new();
group.setName( 'Mask Group' );
// グループ内にマスクの矩形を作成
var maskRect = MSRectangleShape.new();
maskRect.name = 'Mask';
maskRect.frame().x = 0;
maskRect.frame().y = 0;
maskRect.frame().width = 100;
maskRect.frame().height = 150;
var mask = MSShapeGroup.shapeWithPath( maskRect );
group.addLayers( [mask] );
// マスク化
mask.setHasClippingMask( true );
// マスク化による親レイヤーの境界や座標を更新
ビットマップを読み込む
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
// 読み込むファイルのパスを設定
var filePath = '/Users/USERNAME/file/to/path.png';
var image = NSImage.new().initWithContentsOfFile( filePath );
var imageData = MSImageData.alloc().initWithImage_convertColorSpace_(image, true);
var bitmap = MSBitmapLayer.new();
bitmap.image = imageData;
bitmap.name = 'Imported Bitmap';
bitmap.frame().x = 0;
bitmap.frame().y = 0;
artboard.addLayers( [bitmap] );
スライスを作成
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var slice = MSSliceLayer.new();
slice.name = 'Slice Name';
slice.frame().x = 0;
slice.frame().y = 0;
slice.frame().width = 100;
slice.frame().height = 150;
artboard.addSlice( slice );
Radiusの設定
// Rectangleツールで作成した矩形を選択した状態で
var sel = context.selection;
var rect = sel.firstObject().layers().firstObject();
rect.cornerRadiusFloat = 10;
// 個別にRadiusを設定する場合は次の通り
// rect.cornerRadiusString = "7/0/0/10";
Blending Modeの設定
// 矩形レイヤー(rectangle)を作成したのち
var contextSettings = rectangle.style().contextSettings();
contextSettings.blendMode = 1;
Blend Modeの数値は、こちらを参照のこと
レイヤー自体のOpacity設定
// Blending Modeの設定のコードの後に
contextSettings.opacity = 0.5; // 0から1の値
スタイリング
Fill(Flat Color)を設定
// 矩形レイヤー(rectangle)を作成したのち
// Fillを追加してプロパティを取得
var fill = rectangle.style().addStylePartOfType( 0 );
// Fillに適用するカラーを設定
var color = MSImmutableColor.colorWithSVGString( '#ff0000' );
color.alpha = 0.8;
// Fillにカラーを適用
fill.color = color;
addStylePartOfType()
した場合、デフォルトとしてFlat Colorが適用される。Gradientから変更する場合は、fill.setFillType( 0 )
とする。
Fill(Gradient)を設定
// 矩形レイヤー(rectangle)を作成したのち
// Fillを追加してプロパティを取得
var fill = rectangle.style().addStylePartOfType( 0 );
// Fillの種類をGradientに変更
fill.setFillType( 1 );
// Gradientプロパティを取得
var gradient = fill.gradient();
// Gradient Typeの設定 / 0: Linear / 1: Radial / 2: Angular
gradient.setGradientType( 0 );
// Gradient Stopを追加 / value: 0..1
gradient.addStopAtLength( 0.5 );
// Gradient Stopに適用するカラーと透明度を設定
var gradientColor = MSImmutableColor.colorWithSVGString( '#ff0000' );
gradientColor.alpha = 0.8;
// Gradient Stopにカラーを適用
gradient.setColor_atIndex_( gradientColor, 1 );
// Gradient Stopの位置を設定
gradient.setPoint_atIndex_( CGPointMake( 1, 1 ), 1 );
Gradient Stopの位置を設定するCGPointMake()
は、レイヤーの大きさに対する割合をX・Yで指定する。
例えばW100×H100のレイヤーで、CGPointMake( 0.4, 0.5 )
と指定すれば、オブジェクトの左上起点でX40/Y50の位置へGradient Stopが移動する。ただし、atIndex
を両端以外で指定している場合、両端を結ぶ直線上の範囲で移動が行われる。
Fill(Pattern)を設定
// 矩形レイヤー(rectangle)を作成したのち
// Fillを追加してプロパティを取得
var fill = rectangle.style().addStylePartOfType( 0 );
// Fillの種類をPatternに変更
fill.setFillType( 4 );
// 整列方法を設定 / 0: Tile / Fill: 1
fill.setPatternFillType( 1 );
// パターン画像のパスから画像データを作ってFillへ設定する
var imageData = MSImageData.alloc().initWithImage_convertColorSpace_( '/file/to/path/document.png', false );
fill.setImage( imageData );
Fill(Noise)を設定
// 矩形レイヤー(rectangle)を作成したものとする
// Fillを追加してプロパティを取得
var fill = rectangle.style().addStylePartOfType( 0 );
// Fillの種類をNoiseに変更
fill.fillType = 5; // fill.setFillType( 5 )でもOK
// ノイズの種類を指定 / 0: Original / 1: Black / 2: White / 3: Color
fill.noiseIndex = 3;
// IntensityはOpacityとして設定する
fill.contextSettings().opacity = 0.5;
ドロップシャドウ / インナーシャドウ
// 矩形 rectangle を作成済みとして
// 2: ドロップシャドウ / 3: インナーシャドウ
var effect = addStylePart( rectangle, 2 );
// ぼかしの大きさ
effect.blurRadius = 10;
// XY座標
effect.offsetX = 0;
effect.offsetY = 0;
// スプレッドの大きさ
effect.spread = 0;
// 色と不透明度
var color = MSImmutableColor.colorWithSVGString( getHexColor( attrs[i].ShadowColor ) );
color.alpha = getOpacity( attrs[i].ShadowColor );
effect.color = color;
ぼかし各種
// 矩形レイヤー(rectangle)を作成したものとする
var effect = rectangle.style().blur();
// ぼかし効果を有効化
effect.isEnabled = 1;
// 0: ガウス / 1: モーション / 2: ズーム / 3: バックグラウンド(多分)
effect.type = 2;
// ぼかしの大きさ
effect.radius = 10;
テキストレイヤーの作成
var doc = context.document;
var artboard = doc.currentPage().currentArtboard();
var text = MSTextLayer.new();
// 0: Auto(デフォルト) / 1: テキストボックスの幅を固定
text.textBehaviour = 1;
// テキストに文字列を入れる
text.stringValue = 'テキストの内容だよ';
// フォントサイズの設定
text.fontSize = '24';
// フォントの設定(Postscript名で指定する)
text.fontPostscriptName = 'フォント名';
// テキストカラーの設定
text.textColor = MSImmutableColor.colorWithSVGString( '#ff0000' );
// テキストボックスの大きさを最適化
text.adjustFrameToFit();
// パラグラフを設定する
var pragraph = NSMutableParagraphStyle.new();
pragraph.minimumLineHeight = 12;
pragraph.maximumLineHeight = 24;
text.addAttribute_value_( NSParagraphStyleAttributeName, pragraph );
// テキストの揃え - 0: 左 / 1: 右 / 2: 中央
text.setTextAlignment( 0 );
// サイズや位置、レイヤー名なども設定できます
artboard.addLayers( [text] );
文字の一部の設定を変更する
// 変更する範囲を作成(0文字から2文字目まで)
var range = NSMakeRange( 0, 2 );
// フォント名をサイズを指定
var textFont = NSFont.fontWithName_size_( 'フォント名(Postscript)', 24 );
// 色を指定
var color = MSImmutableColor.colorWithSVGString( '#ff0000' );
// 一部の変更を実行
text.setIsEditingText( true );
text.addAttribute_value_forRange_( NSFontAttributeName, textFont, range );
text.addAttribute_value_forRange_( NSForegroundColorAttributeName, color, range );
text.setIsEditingText( false );
// パラグラフも設定できますが、多分一部だけを変えることはないでしょうね
text.addAttribute_value_forRange_( NSParagraphStyleAttributeName, pragraph, range );
Symbol
アートボードからシンボルを作成する
あらかじめSymbolにするアートボードを作成しておくこと。
MSSymbolMaster.convertArtboardToSymbol( artboard );
// artboard = あらかじめ作成していたアートボード
ただこれではインスタンスを作成しづらいので、オブジェクトに放り込んでおくと良い…かも?
var symbols['symbolName'] = MSSymbolMaster.convertArtboardToSymbol( artboard );
Symbol Instanceの作成
var doc = context.document;
var cp = doc.currentPage();
for( var i = 0; i < doc.pages().count(); i++ ) {
if( 'Symbols' == doc.pages()[i].name() ) {
var symbolsPage = doc.pages()[i];
break;
}
}
var symbolInstance = symbolsPage.artboards()[0].newSymbolInstance();
symbolInstance.setName( 'Symbol Instance' );
symbolInstance.frame().x = 0;
symbolInstance.frame().y = 100;
cp.addLayers( [symbolInstance] );
メッセージ・ダイアログ関連
参考
ウィンドウ下部へメッセージ
// JS Style
doc.showMessage( 'Message' );
// Obj-c style
[doc showMessage: 'Meaasage'];
Cocoaでモーダルダイアログ
アイコンとかも設定できるはず。
// JS Style
var userInput = COSAlertWindow.new();
//ダイアログタイトル
userInput.setMessageText( 'Dialog Title' );
// テキストフィールド
userInput.addTextLabelWithValue( 'Text Field Title' );
userInput.addTextFieldWithValue( 'Text Field Placeholder' );
// チェックボックス
var checkbox = NSButton.alloc().initWithFrame( NSMakeRect( 0, 0, 300, 18 ) );
checkbox.setButtonType( NSSwitchButton );
checkbox.setTitle( 'Switch Button Title' );
checkbox.setTag( 'value' );
checkbox.setState( false );
userInput.addAccessoryView( checkbox );
// ラジオボタン
var radiobutton = NSButton.alloc().initWithFrame( NSMakeRect( 0, 0, 300, 18 ) );
radiobutton.setButtonType( NSRadioButton );
radiobutton.setTitle( 'Radio Button Title' );
radiobutton.setTag( 'value' );
radiobutton.setState( true );
userInput.addAccessoryView( radiobutton );
// ボタン
userInput.addButtonWithTitle('OK');
// 実行
userInput.runModal();
// Obj-c style
var userInput = [COSAlertWindow new];
//ダイアログタイトル
[userInput setMessageText:'Dialog Title'];
// テキストフィールド
[userInput addTextLabelWithValue:'Text Field Title'];
[userInput addTextFieldWithValue:'Text Field Placeholder'];
// チェックボックス
var checkbox = [[NSButton alloc] initWithFrame:NSMakeRect( 0, 0, 300, 18 )];
[checkbox setButtonType:NSSwitchButton];
[checkbox setTitle: 'Switch Button Title'];
[checkbox setTag: 'value'];
[checkbox setState: false];
[userInput addAccessoryView: checkbox];
// ラジオボタン
var radiobutton = [[NSButton alloc] initWithFrame:NSMakeRect( 0, 0, 300, 18 )];
[radiobutton setButtonType: NSRadioButton];
[radiobutton setTitle: 'Radio Button Title'];
[radiobutton setTag: 'value'];
[radiobutton setState: true];
[userInput addAccessoryView: radiobutton];
// ボタン
[userInput addButtonWithTitle: 'OK'];
// 実行
[userInput runModal];
setButtonTypeはこのあたりを参照
Fw.jsf でいう、prompot();
// JS Style
var userInput = doc.askForUserInput_initialValue( 'Message', 'Default Value' );
// Obj-c style
var position = [doc askForUserInput: 'Message' initialValue: 'Default Value'];
JavaScript スタイルの書き方が分からなかったが、「_」でつなぐと良いことを教わった。
JSONファイルを選択してパース
ただし、runModalForDirectory
が10.6で非推奨になっているので、他の方法を探す(10.10でも一応動作可能)。
var openPanel = NSOpenPanel.openPanel();
openPanel.setTitle( "Choose a JSON File" ); // ダイアログのタイトル
openPanel.setCanCreateDirectories = false; // ディレクトリの作成を許可するか
openPanel.setCanChooseFiles = true; // ファイル選択を許可するか
var fileTypes = ['json']; // 選択できるファイルタイプを設定
var openPanelButtonPressed = openPanel.runModalForDirectory_file_types_( nil, nil, fileTypes );
if ( openPanelButtonPressed == NSFileHandlingPanelOKButton ) {
var filePath = openPanel.URL().path();
var json = JSON.parse( NSString.stringWithContentsOfFile( filePath ) );
log( 'Open File from: ' + filePath );
} else {
return false;
}
そのほか
フォントの一覧を取得
var fontList = NSFontManager.sharedFontManager().availableFontFamilies();
フォントファミリーを取得
var fontFamilies = NSFontManager.sharedFontManager().availableMembersOfFontFamily('Helvetica Neue');
引数として、フォント名を渡す。PostScript名はNGで、「フォントの一覧」で取得したフォント名を使うこと。
ArrayからJSONに
例えば上記の「フォントの一覧」から作成する場合
var fontList = NSFontManager.sharedFontManager().availableFontFamilies();
var data = NSJSONSerialization.dataWithJSONObject_options_error_(fontList, 0, nil);
var json = NSString.alloc().initWithData_encoding_(data, 4);
Plugins Directoryへの登録
オリジナルドキュメント:Contributing
GitHubやウェブサイト等へアクセスし、ダウンロードできるように準備しておく。
- Sketch Plugins DirectoryのリポジトリをForkし、ローカルへCloneする。
-
plugins.json
を編集する。- Object(
{}
の括り)をコピペする。 - それぞれの項目を英語で埋める。Google翻訳したような英語でも問題なさそう。
最低限、description
(プラグインの説明)・name
(リポジトリ名)・title
(プラグイン名)・owner
(リポジトリの所有者名)を埋める。
そのほかの情報として、owner
(作者名 リポジトリ所有者名以外を使う場合)・homepage
(リポジトリ以外でプラグインを配布している場合のリンク先)・lastUpdated
(最終更新日)がある。 - 不安なら、適当なJSON linterを通しておく。
- Object(
- Terminal.appで、Cloneしたディレクトリへ移動し、
rake
コマンドを実行すると、plugins.json
に合わせて、README.md
が更新される。 - リモートのリポジトリへプッシュし、元のリポジトリへPull Requestを送る。メッセージは何でもOK。