Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

ディスプレイの輝度変更

Posted on 1月 5, 2020 by Takaaki Naganoya

ディスプレイの輝度変更を行うAppleScriptです。

AppleScriptにディスプレイの輝度変更を行う機能はないので、GUI Scripting経由で(画面上のGUI部品を野蛮に操作して)変更するか、あるいは「他の方法」を採用することになります。

本Scriptは「他の方法」をとってみたものです。画面の輝度変更については、そのようなニーズがあり、割とまともにOSに機能が実装されていることもあり、IOKitを呼び出して変更している例がいろいろ見つかります(Objective-Cとかで)。そういったものをFramework化してAppleScriptから呼び出すか、あるいはコマンドライン上で動作するプログラムをAppleScript内に入れて呼び出すか、といったところになります。

Github上で探し物をしてみたところ、nriley氏の「brightness」というツールがコマンドライン上から呼び出せるようになっており、AppleScriptのバンドル内に突っ込んで呼び出しやすそうでした。

そこで、実際にAppleScriptバンドル書類中に突っ込んで、いい感じに呼び出せるように最低限の機能を実装してみました。ディスプレイの接続数の確認(getDisplayNumber)、指定ディスプレイの現在の輝度確認(getBrightNess)、そして指定ディスプレイの輝度設定(setBrightNess)です。

–> Download displayBrightness.scptd (Script Bundle with brightness binary in its bundle)

ディスプレイ番号は1から始まるものとして扱っています。輝度は0.0〜1.0(1.0が一番明るい)までの値を指定します。

一応、brightnessユーティリティでは複数のディスプレイが接続された状態を前提に処理しているのですが、どうせ輝度変更ができるのはMacBook ProやiMacなどの内蔵ディスプレイだけです。外部接続したディスプレイの輝度は変更できません。

本Scriptのようなお気楽実装だと問題になってくるのが、

(1)デスクトップマシン(MacPro、Mac miniなど)で外部ディスプレイを接続していない(ヘッドレス運用)の場合への対処
(2)ノート機+iMac/iMac Proで、メインディスプレイを本体内蔵ディスプレイ「以外のもの」に指定している場合への対処
(3)ノート機で、Lid Closed Mode運用している(本体を閉じて外部ディスプレイをつないで使っている)状態への対処

などです。本Scriptはそこまで厳密な対応を行っていません。ただ、実用上はこのぐらいで問題はなさそうだ、という「割り切り」を行って手を抜いています。

各条件でテストを行って「使える」という確証が得られたら、sdef(AppleScript用語辞書)をつけたライブラリにでもするとよさそうです。

また、本Script中に同梱しているbrightnessツールの実行ファイルはNotarizationを通していないため、2020年2月3日を過ぎると10.15.2以降のmacOSで何らかのダイアログが出て実行をキャンセルされる可能性がありますが、正直なところmacOS 10.15.xは「バグが多すぎ」「実用性なし」と判断。macOS 10.15.xは自分としては「パス」するつもりなので、現時点において対処する必要性を感じません(仕事で納品するバイナリについては全力で対処しますが)。

AppleScript名:displayBrightness.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/01/04
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set dRes to getDisplayNumber() of me
–> 1

set bRes to getBrightNess(1) of me
–> 0.763672

set sRes to setBrightNess(1, 0.7) of me

on getDisplayNumber()
  set myPath to POSIX path of (path to me)
  
set cmdPath to myPath & "Contents/Resources/brightness"
  
set aRes to do shell script quoted form of cmdPath & " -l"
  
set pList to paragraphs of aRes
  
return (length of pList) div 2
end getDisplayNumber

on getBrightNess(displayNumber as integer)
  set dRes to getDisplayNumber() of me
  
if dRes < displayNumber then error "Your parameter is too large (" & "there is " & (dRes as string) & " display only)."
  
  
set targDispNumber to displayNumber – 1
  
set targString to "display " & (targDispNumber as string) & ": brightness "
  
  
set myPath to POSIX path of (path to me)
  
set cmdPath to myPath & "Contents/Resources/brightness"
  
set aRes to do shell script quoted form of cmdPath & " -l"
  
  
repeat with i in (paragraphs of aRes)
    set j to contents of i
    
if j begins with targString then
      set aOffset to offset of targString in j
      
set resStr to text (aOffset + (length of targString)) thru -1 of j
      
return resStr
    end if
  end repeat
  
  
error "Display’s brightness information is not present"
end getBrightNess

on setBrightNess(displayNumber as integer, targBrightnewss as real)
  set dRes to getDisplayNumber() of me
  
if dRes < displayNumber then error "Your parameter is too large (" & "there is " & (dRes as string) & " display only)."
  
  
set targDispNumber to displayNumber – 1
  
set targString to "display " & (targDispNumber as string) & ": brightness "
  
  
set myPath to POSIX path of (path to me)
  
set cmdPath to myPath & "Contents/Resources/brightness"
  
set aRes to do shell script quoted form of cmdPath & " -l"
  
  
set hitF to false
  
repeat with i in (paragraphs of aRes)
    set j to contents of i
    
if j begins with targString then
      set hitF to true
      
exit repeat
    end if
  end repeat
  
  
if hitF = false then error "There is no display (" & (displayNumber as string) & ")"
  
  
set bRes to do shell script quoted form of cmdPath & " " & (targBrightnewss as string)
  
  
set curBright to getBrightNess(displayNumber) of me
  
  
–結果を評価する
  
if (targBrightnewss as real) is not equal to (curBright as real) then
    return false
  else
    return true
  end if
end setBrightNess

★Click Here to Open This Script 

Posted in System | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | Leave a comment

Double PDF v2 Now On Sale

Posted on 1月 3, 2020 by Takaaki Naganoya

Mac App Storeで、Piyomaru SoftwareによるMac用アプリケーション「Double PDF」の新バージョンv2.0をリリースしました。100% AppleScriptで記述しています。

本バージョンは、macOS 10.13においてScripting Bridge経由でPDFViewを正しくアクセスできないバグが発生している症状を回避したものです。表示中のページ管理などをすべてアプリケーション側で行うことにより、機能の回復を実現しました(書いていて情けない)。

v1ではGPUImage.frameworkを利用して画像処理していましたが、これを取り外してすべてAppleScriptで処理するように変更しました。

■v2.0の追加機能
・ダークモード対応
・画像比較時のカラーモード追加(従来はグレースケールのみ)
・30言語に対応(English, Catalan, Chinese, Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hindi, Hungarian, Indonesian, Italian, Japanese, Korean, Malay, Norwegian Bokmål, Polish, Portuguese, Romanian, Russian, Simplified Chinese, Slovak, Spanish, Swedish, Thai, Traditional Chinese, Turkish, Ukrainian, Vietnamese)
・Unicode文字の「Zero Width Space」削除機能を追加

■v2.0の修正機能
・順次Diffチェック時に、アプリケーションアイコン上に描画するプログレスバーの進捗度が間違っていたのを修正

Posted in PRODUCTS Release | Tagged 10.13savvy 10.14savvy 10.15savvy | Leave a comment

A Happy New Year

Posted on 1月 1, 2020 by Takaaki Naganoya

Posted in news | Leave a comment

指定文字列のAppleScriptを実行してエラー詳細を取得

Posted on 1月 1, 2020 by Takaaki Naganoya

指定文字列のAppleScriptをコンパイル(構文確認、中間コードへのコンパイル)、実行してエラーの詳細を取得するAppleScriptです。

AppleScript名:指定文字列のAppleScriptを実行してエラー詳細を取得.scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2020/01/01
—
–  Copyright © 2020 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set asSourceString to "set a to 123
beepz"
–This AppleScript text has an error

set asObj to current application’s NSAppleScript’s alloc()’s initWithSource:(asSourceString)

–AppleScriptオブジェクトがコンパイル(構文確認、中間コードへの解釈)ずみかどうかをチェック
set isCompiledF1 to asObj’s isCompiled()
–> false

–コンパイル(構文確認)してエラー確認
set isCompiledF2 to asObj’s compileAndReturnError:(reference)
–> {true, missing value}

set exeRes1 to asObj’s executeAndReturnError:(reference)
–> {<NSAppleEventDescriptor: null()>, missing value}–No error

–> {missing value, (NSDictionary) {NSAppleScriptErrorMessage:"beepz変数は定義されていません。", NSAppleScriptErrorBriefMessage:"beepz変数は定義されていません。", NSAppleScriptErrorNumber:-2753, NSAppleScriptErrorRange:(NSConcreteValue) NSRange: {13, 5}}}

★Click Here to Open This Script 

Posted in OSA | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAppleScript | Leave a comment

display text fields Library v1.3

Posted on 12月 31, 2019 by Takaaki Naganoya

「display text fields」AppleScriptライブラリをv1.3にアップデートしました。

–> Download display text fields_v13 (To ~/Library/Script Libraries/)

v1.3ではテキストフィールドの最大横幅の計算を修正し、フィールド数が増えたときにダイアログ上から項目がはみ出さないようにScroll Viewをつけるようにしました。

本来目的としていた用途に使ってみたらイマイチだった点を修正した格好です。AppleScriptで取得した各種アプリケーションのオブジェクトのプロパティ情報をダイアログ上で一覧表示して確認するというのが、自分がこのライブラリを作った目的です。

以下は、サンプルスクリプト「文字列で指定したAppleScriptの実行結果をテキストで取得する v2」についての説明です。

割とえげつない処理をしていますが、作りためておいたルーチンを引っ張り出してきただけなので、書くのにさほど時間はかけていません。

こうしたAppleScriptのプロパティ値をparseするには、スクリプトエディタの結果欄を文字列として取得するか(GUI Scripting経由でやったことがあります)、こうしてメモリ上にスクリプトエディタ+結果表示用のビューを生成してメモリ上でAppleScriptを実行して結果をテキストで取得するということになると思います。前者だとGUI Scriptingの実行権限が必要になるため、Cocoaの機能を利用したほうが手軽という状況です。

(途中で入れ替えた)v2では、macOS 10.15対応、ランタイム環境によってはうまく動かない「as anything」の使用をやめるなどの変更を加えました。

AppleScript名:文字列で指定したAppleScriptの実行結果をテキストで取得する v2.scpt
— Created 2016-01-08 by Takaaki Naganoya
— 2016 Piyomaru Software
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "OSAKit"
use framework "AppKit"
use tfLib : script "display text fields"

property OSAScript : a reference to current application’s OSAScript
property NSTextView : a reference to current application’s NSTextView
property OSAScriptView : a reference to current application’s OSAScriptView
property OSAScriptController : a reference to current application’s OSAScriptController

property myRes : ""

–OSのメジャーバージョンを数値で取得
set osVer to system attribute "sys2"

if osVer ≥ 15 then
  set srcStr to "tell application \"Music\"
  set aSel to first item of selection
  set aRes to (properties of aSel)
end tell"
else
  set srcStr to "tell application \"iTunes\"
  set aSel to first item of selection
  set aRes to (properties of aSel)
end tell"
end if

my performSelectorOnMainThread:"getResultStringFromScript:" withObject:(srcStr) waitUntilDone:true

set aRes to getListFromText(myRes) of me

set aList to {}
set bList to {}
set aLen to length of aRes

repeat with i from 1 to aLen
  set {aCon, bCon} to contents of item i of aRes
  
set the end of aList to aCon
  
set the end of bList to bCon
end repeat

confirm text fields main message "Track Info" sub message "Properties about selected track" key list aList value list bList

–Get AppleScript’s Result as string
on getResultStringFromScript:paramObj
  set srcStr to paramObj as string
  
set myRes to ""
  
  
set targX to 500 –View Width
  
set targY to 200 –View Height
  
  
set osaCon to OSAScriptController’s alloc()’s init()
  
set osaView to OSAScriptView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
  
set resView to NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, targX, targY))
  
resView’s setRichText:true
  
resView’s useAllLigatures:true
  
  
osaCon’s setScriptView:osaView
  
osaCon’s setResultView:resView
  
  
osaView’s setString:srcStr
  
osaCon’s runScript:(missing value)
  
  
set myRes to resView’s |string|() as string
end getResultStringFromScript:

–スクリプトエディタのresult欄に返ってきたテキストをリストに変える
on getListFromText(aText)
  
  
script getListFromTextO
    property aaText : ""
    
property gList : {}
    
property outList : {}
    
property aG : ""
    
property valList : {}
  end script
  
  
copy aText to (aaText of getListFromTextO)
  
  
set (gList of getListFromTextO) to {}
  
set (outList of getListFromTextO) to {}
  
set (aG of getListFromTextO) to ""
  
set (valList of getListFromTextO) to {}
  
  
if (aaText of getListFromTextO) does not start with "{" and (aaText of getListFromTextO) does not end with "}" then
    return {}
  end if
  
  
set aLen to length of (aaText of getListFromTextO)
  
set (aG of getListFromTextO) to text 2 thru -2 of (aaText of getListFromTextO)
  
set (gList of getListFromTextO) to characters of (aG of getListFromTextO)
  
  
  
set sPos to 2 –1文字目は\"{\"なので2文字目からスキャンを開始する
  
set ePos to 2
  
  
set imdF to false –Immediate Data Flag(文字列中を示すダブルクォート内の場合にはtrueになる)
  
set listF to 0 –stacking段数が入る
  
  
set attrF to true –属性ラベルスキャン時にtrue、データ末尾スキャン時にfalse
  
  
  
repeat with i in (gList of getListFromTextO)
    
    
set j to contents of i
    
    
if attrF = true and imdF = false and listF = 0 then
      
      
–属性値部分の末尾検出
      
if j = ":" then
        if text sPos thru sPos of (aaText of getListFromTextO) = " " then
          set sPos to sPos + 1
        end if
        
set anOut to text sPos thru ePos of (aaText of getListFromTextO)
        
set sPos to ePos + 1
        
set the end of (valList of getListFromTextO) to anOut
        
set attrF to false –データのスキャンを開始する
        
set imdF to false
        
set listF to 0
      end if
      
    else if imdF = false and listF = 0 and j = "," then
      
      
–データ部分の末尾検出
      
set anOut to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
      
set sPos to ePos + 1
      
set the end of (valList of getListFromTextO) to anOut
      
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
      
set (valList of getListFromTextO) to {}
      
      
set attrF to true –次が属性値ラベルであることを宣言
      
set imdF to false
      
set listF to 0
      
    else if j = "{" then
      if imdF = false then
        set listF to listF + 1 –1段スタックにpush
      end if
    else if j = "}" then
      if imdF = false then
        set listF to listF – 1 –1段スタックからpop
      end if
    else if j = "\"" then
      if imdF = true then
        set imdF to false
      else
        set imdF to true
      end if
    end if
    
    
set ePos to ePos + 1
    
  end repeat
  
  
–ラストのデータ部分を出力
  
try
    set the end of (valList of getListFromTextO) to text sPos thru (ePos – 1) of (aaText of getListFromTextO)
    
set the end of (outList of getListFromTextO) to (valList of getListFromTextO)
  on error
    false
  end try
  
  
return contents of (outList of getListFromTextO)
  
end getListFromText

★Click Here to Open This Script 

Posted in dialog GUI OSA | Tagged 10.13savvy 10.14savvy 10.15savvy iTunes NSTextView OSAScript OSAScriptController OSAScriptView | Leave a comment

SVGのPath指定をParseしてx,y座標の最小値、最大値を求める

Posted on 12月 30, 2019 by Takaaki Naganoya

SVGのPath指定(相対座標指定)をparseして、x,y座標の最小値、最大値を求めるAppleScriptです。

SVGで作られた世界地図を表示し、指定の国を赤く塗るというAppleScriptを試作したことがありました(choose countryといった命令を作る野望が)。しかし、メルカトル図法の世界地図で塗った箇所がわからないぐらいの規模の国が世界中にはたくさんあることを再認識しただけでした。つまり、アメリカ合衆国とかロシアとか中華人民共和国ぐらい国土が広ければ赤く塗っておけば視認できますが、赤く塗っても面積が小さければ視認できません。

そこで、地図上では「点」にしか見えないような国の位置を明示するためには、色を変えて塗る以外の表現方法が必要になってきます。

SVG世界地図上では、それぞれの国データがpathで表現されていました。このpathはすべてを絶対座標で表現するタイプと相対座標で表現するタイプがあり、部品として使いまわしたりデータサイズを抑えることを考えれば、相対座標でデータ表現したくなることでしょう。実際、自分が見つけたSVG世界地図データは相対座標でデータが作られていました。

そこで、指定のPath内の座標値をすべて絶対座標に計算し直しつつ、x,y座標の最小値、最大値を求め、その値を元に塗りつぶすことで、面積の小さな国の所在位置を赤い線の交点として表現できそうだと考えました。

そうした実証実験のために作成したのが本AppleScriptです。

テストデータは日本列島のもので、このサイズのデータからx,yの最小値、最大値を計算するのに0.06秒ぐらいで処理できています(自分の開発環境での計測値です)。プログラムの作りやすさを優先して、あとで全データから最大値/最小値を求めていますが、座標計算しながら最大値/最小値を求めれば、0.05秒ぐらいにはなると思います。
→ 同時に計算したら0.039秒で済みました

座標データ数がそれほど多くないので、Cocoaの機能を利用しても大幅な速度向上は見込めません。


▲アンドラ公国


▲バチカン市国


▲米領サモア

本Scriptで取得したPathの最小値、最大値をもとに塗りつぶしを行なってみたところ、地図上で1ドットにも満たないような面積の国でも所在位置がわかるように表現できました。

面積に応じて、塗りつぶし時のアルファ値を変更するような処理もためしていますが、面積が広いのに点にも見えない国(島で構成される国)だと、対象が見えないのに塗りつぶし色が薄くて見にくいなど、まだいろいろ試行錯誤が必要なようです。

AppleScript名:parseSVGPath.scptd
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

script spd
  property dStr : ""
  
property dList : {}
  
property d2List : {}
  
property d3List : {}
  
property absX : {}
  
property absY : {}
end script

–Initialize
set (dStr of spd) to retData() of me
set (dList of spd) to parseByDelim((dStr of spd), {"m ", " z"}) of me
set (d2List of spd) to {}

–Parse into each stroke
repeat with i in (dList of spd)
  set j to contents of i
  
if j is not equal to "" then
    set d3 to parseByDelim(j, " ") of me
    
if d3 is not equal to "" then
      set the end of (d2List of spd) to d3
    end if
  end if
end repeat

set (d3List of spd) to FlattenList((d2List of spd)) of me
set origPos to first item of (d3List of spd)
set (d3List of spd) to rest of (d3List of spd)
set {origX, origY} to parseByDelim(origPos, ",") of me

set origX to origX as real
set origY to origY as real

set (absX of spd) to {}
set (absY of spd) to {}

set the end of (absX of spd) to origX
set the end of (absY of spd) to origY

–絶対座標のリストに変換する
repeat with i in (d3List of spd)
  set j to contents of i
  
if j is not equal to "" then
    set {curX, curY} to parseByDelim(j, ",") of me
    
    
set origX to origX + (curX as real)
    
set origY to origY + (curY as real)
    
    
set the end of (absX of spd) to origX
    
set the end of (absY of spd) to origY
  end if
end repeat

set minX to minimumFromList((absX of spd)) of me
set maxX to maximumFromList((absX of spd)) of me
set minY to minimumFromList((absY of spd)) of me
set maxY to maximumFromList((absY of spd)) of me

return {{minX, minY}, {maxX, maxY}}

–最大値を取得する
on maximumFromList(nList)
  script o
    property NL : nList
  end script
  
  
set max to item 1 of o’s NL
  
repeat with i from 2 to (count nList)
    set n to item i of o’s NL
    
if n > max then set max to n
  end repeat
  
return max
  
end maximumFromList

–最小値を取得する
on minimumFromList(nList)
  script o
    property NL : nList
  end script
  
  
set min to item 1 of o’s NL
  
repeat with i from 2 to (count nList)
    set n to item i of o’s NL
    
if n < min then set min to n
  end repeat
  
return min
  
end minimumFromList

on parseByDelim(aData, aDelim)
  set curDelim to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to aDelim
  
set dList to text items of aData
  
set AppleScript’s text item delimiters to curDelim
  
return dList
end parseByDelim

on FlattenList(aList)
  set oldDelims to AppleScript’s text item delimiters
  
set AppleScript’s text item delimiters to {"????"}
  
set aString to aList as text
  
set aList to text items of aString
  
set AppleScript’s text item delimiters to oldDelims
  
return aList
end FlattenList

on retData()
  return "m 878.53675,325.4254 0.352,0.02 0.157,-0.018 0.269,0.059 1.067,0.591 0.322,0.075 0.333,0.009 0.234,-0.048 0.206,-0.162 0.644,-0.717 0.678,-0.655 0.075,0.025 0,0.181 -0.05,0.201 -0.3,0.599 -0.333,0.804 -0.071,0.406 0.108,0.395 0.209,0.326 0.165,0.445 0.19,0.617 0.268,0.078 0.146,0.009 0.268,-0.185 0.253,-0.235 0.218,-0.029 0.229,0.04 -0.301,0.164 -0.284,0.2 -0.244,0.378 -0.091,0.071 -0.281,-0.023 -0.161,0.014 -0.329,0.158 -0.289,0.179 -0.276,0.219 -0.301,0.117 -0.321,0.028 -0.495,0.179 -0.321,0.013 -0.603,-0.156 -0.293,0.042 -0.639,0.352 -0.582,0.508 -0.509,0.569 -0.425,0.682 -0.171,0.354 -0.103,0.396 -0.014,0.262 -0.038,0.251 -0.098,0.175 -0.118,0.142 -0.351,-0.083 -0.576,-0.362 -1.117,-0.527 -1.18,-0.809 -0.664,-0.407 -1.248,0.122 -1.181,0.776 -0.105,-0.066 -0.451,-0.532 -0.219,-0.211 -0.261,-0.06 -0.194,0.007 -0.188,0.039 -0.267,0.274 -0.098,0.197 -0.076,0.224 -0.023,0.158 0.032,0.155 0.253,0.35 0.312,0.26 0.141,0.049 0.299,-0.018 0.139,0.027 0.501,0.521 0.549,0.488 0.121,0.161 -0.203,0.169 -0.222,0.084 -0.259,-0.021 -0.256,-0.064 -0.438,-0.207 -0.188,0.176 -0.292,0.361 -0.161,0.392 -0.131,0.179 -0.322,0.236 -0.341,0.122 -0.179,-0.04 -0.136,-0.148 -0.077,-0.177 -0.039,-0.206 0.072,-0.446 0.177,-0.403 0.068,-0.412 -0.145,-0.581 -0.092,-0.122 -0.362,-0.341 -0.168,-0.333 -0.04,-0.415 0.021,-0.229 0.088,-0.507 0.088,-0.256 0.166,-0.084 0.182,-0.051 0.279,-0.184 0.307,-0.238 0.294,-0.272 0.291,-0.333 0.151,-0.366 -0.249,-0.45 -0.052,-0.268 0.037,-0.253 0.266,-0.135 0.273,0.102 0.551,0.372 0.107,0.037 0.378,0.017 0.518,0.081 0.3,-0.02 0.145,-0.056 0.218,-0.307 0.107,-0.392 -0.039,-0.505 -0.002,-0.502 0.138,-0.41 0.432,-0.661 0.124,-0.39 0.045,-0.952 0.156,-0.42 0.125,-0.437 0.06,-0.918 -0.177,-0.886 -0.178,-0.436 -0.204,-0.415 0.03,-0.397 0.165,-0.369 0.004,-0.111 0.039,-0.099 0.309,-0.07 0.145,-0.079 0.139,-0.178 0.165,-0.104 0.121,0.104 0.1,0.182 0.436,0.447 0.687,0.796 0.809,1.209 0.507,0.587 0.534,0.531 0.599,0.542 0.627,0.465 0.4,0.22 0.293,0.35 0.181,0.057 z m -7.723,-4.787 -0.108,0.252 -0.146,-0.375 -0.029,-0.405 0.084,0.002 0.154,0.061 0.037,0.197 0.008,0.268 z m 0.625,0.848 -0.194,0.028 -0.227,-0.166 -0.028,-0.208 0.164,-0.166 0.163,0.061 0.163,0.214 0.054,0.112 -0.095,0.125 z m -5.091,11.738 -0.064,0.02 -0.066,-0.032 -0.065,-0.285 0.056,-0.15 0.181,-0.105 0.176,-0.029 -0.149,0.524 -0.069,0.057 z m 4.906,2.653 0.11,0.07 0.524,-0.189 -0.1,0.571 -0.056,0.575 0.038,0.952 0.047,0.428 0.091,0.414 0.224,0.296 0.292,0.21 0.423,0.669 0.227,0.82 0.16,0.397 0.12,0.416 0.037,0.19 0.003,0.19 -0.036,0.26 0.04,0.21 -0.046,0.658 -0.189,0.759 -0.024,0.387 -0.165,0.077 -0.1,0.179 -0.085,0.083 -0.095,0.064 -0.137,0.016 -0.099,0.073 -0.039,0.205 -0.063,0.189 -0.12,0.175 -0.094,0.192 -0.077,0.468 -0.028,0.479 -0.115,0.334 -0.279,0.087 -0.319,-0.005 -0.409,0.154 -0.088,0.091 -0.323,0.582 -0.093,0.341 -0.003,0.366 0.09,0.45 0.122,0.439 0.092,0.815 -0.097,1.238 -0.094,0.395 -0.205,0.267 -0.156,0.124 -0.134,0.152 -0.174,0.401 -0.288,0.798 -0.023,0.2 10e-4,0.207 -0.078,0.27 -0.05,0.265 0.047,0.308 0.089,0.288 0.386,0.737 0.151,0.218 0.17,0.198 -0.659,0.219 -0.118,0.101 -0.392,0.418 -0.125,0.396 0.01,0.438 -0.065,0.157 -0.107,0.136 -0.112,0.09 -0.438,0.2 -0.28,0.199 -0.278,0.311 -0.11,0.162 -0.215,-0.052 -0.126,-0.144 0.124,-0.18 -0.038,-0.213 0.061,-0.547 -0.069,-0.22 0.224,-0.167 0.106,-0.266 0.232,-0.213 0.167,-0.189 0.029,-0.154 -0.149,-0.166 -0.158,-0.12 -0.218,0 -0.21,0.035 -0.137,0.158 -0.045,0.215 0.011,0.1 -0.018,0.087 -0.33,0.294 0.043,0.307 0.097,0.156 0.124,0.074 -0.037,0.105 -0.157,0.247 -0.109,0.024 -0.201,-0.346 -0.252,-0.189 -0.312,10e-4 -0.32,0.069 -0.243,0.23 -0.08,0.191 -0.052,0.197 0.018,0.479 -0.101,0.4 -0.198,0.351 -0.092,0.128 -0.241,0.238 -0.167,0.031 -0.118,-0.108 -0.096,-0.164 0.122,-0.6 -0.005,-0.338 0.282,-0.172 -0.231,-0.24 -0.284,-0.097 -0.399,0.128 -0.113,0.145 -0.077,0.194 -0.215,0.246 -0.236,0.229 -0.269,0.392 -0.18,0.463 -0.59,-0.151 -0.321,-0.034 -0.325,0.012 -0.576,-0.057 -0.632,0.095 -0.72,0.182 0.043,-0.131 0.592,-0.279 0.021,-0.082 -0.057,-0.153 -0.147,-0.007 -0.354,0.053 -0.181,-0.023 -0.073,-0.164 -0.12,-0.07 -0.08,0.067 0.026,0.318 -0.087,0.042 -0.117,-0.082 0.037,-0.248 -0.079,-0.363 -0.01,-0.226 0.124,-0.194 -0.127,-0.082 -0.134,0.031 -0.17,0.093 -0.15,0.132 -0.317,0.663 -0.123,0.378 0.232,0.303 0.634,0.423 0.108,0.104 0.002,0.18 -0.077,0.191 -0.172,0.083 -0.695,0.141 -0.603,0.273 -0.174,0.276 -0.548,1.066 -0.439,0.727 -0.62,0.25 -0.68,-0.223 -0.165,-0.253 -0.133,-0.313 -0.253,-0.283 -0.229,-0.309 -0.133,-0.367 0.021,-0.592 -0.099,-0.357 0.089,-0.095 0.375,-0.218 0.123,-0.122 0.212,-0.284 0.076,-0.158 0.011,-0.239 -0.17,-0.125 -0.44,0.004 -0.439,0.075 -0.313,-0.104 -0.407,-0.29 -0.126,-0.062 -0.438,-0.018 -0.313,0.054 -0.307,0.105 -0.325,0.034 -0.108,0.055 -0.375,0.355 -0.299,0.223 -0.258,0.111 -0.557,0.029 -0.279,0.072 -0.292,0.117 -0.082,-0.01 -0.308,0.162 -0.354,0.14 -0.188,0.14 -0.347,-0.092 -0.686,0.251 -0.332,0.031 -0.342,-0.139 -0.318,-0.225 -0.305,0.097 -0.209,0.331 -0.102,0.658 -0.119,0.296 -0.036,0.355 -0.158,-0.056 -0.918,-0.639 -0.063,-0.023 -0.742,0.11 -0.191,0.053 -0.239,0.129 -0.253,0.058 -0.23,-0.093 -0.221,-0.151 -0.212,0.045 -0.217,0.106 -0.084,-0.966 0.043,-0.127 0.133,-0.169 0.147,-0.145 0.359,-0.05 0.363,0.047 0.26,-0.066 0.22,-0.192 0.231,-0.272 0.261,-0.222 0.354,-0.175 0.342,-0.201 0.301,-0.282 0.285,-0.309 0.262,-0.227 0.285,-0.19 0.434,-0.458 0.575,-0.515 0.221,-0.382 0.137,-0.105 0.495,-0.213 0.657,-0.164 0.31,0.008 0.306,0.335 0.165,-0.046 0.168,-0.087 0.338,-0.048 0.348,0.056 0.34,0.001 0.34,-0.042 0.652,-0.11 0.344,-0.133 0.336,-0.172 1.196,-0.121 0.819,-0.289 0.13,0.021 0.126,0.066 0.01,0.214 -0.104,0.233 0.101,0.141 0.166,0.087 0.771,0.027 0.22,0.05 0.322,-0.159 0.304,-0.197 0.317,-0.26 0.222,-0.293 -0.205,-0.367 -0.045,-0.402 0.172,-0.437 0.249,-0.368 0.296,-0.223 0.273,-0.257 0.552,-0.73 0.399,-0.592 0.144,-0.73 -0.084,-0.866 0.349,-0.646 0.334,-0.111 0.663,-0.295 0.348,-0.086 0.052,0.129 -0.01,0.169 -0.521,0.542 -0.299,0.223 -0.178,0.069 -0.164,0.098 -0.067,0.191 0.266,0.318 0.067,0.235 -0.017,0.225 0.012,0.203 0.3,0.22 0.345,0.073 0.144,-0.002 0.126,-0.058 0.394,-0.539 0.088,-0.094 1.12,-0.396 0.551,-0.303 0.305,-0.079 0.286,-0.158 0.642,-0.61 0.236,-0.282 0.215,-0.312 0.172,-0.363 0.136,-0.393 0.186,-0.245 1.017,-0.585 0.327,-0.319 0.104,-0.155 0.126,-0.449 0.087,-0.467 0.123,-0.367 0.167,-0.344 0.223,-0.351 0.251,-0.327 0.148,-0.335 0.216,-0.803 0.094,-0.446 0.074,-0.161 0.108,-0.135 0.094,-0.172 0.072,-0.192 0.033,-0.19 0.046,-0.582 -0.028,-0.454 -0.168,-0.385 -0.139,-0.109 -0.151,-0.006 -0.228,0.033 -0.193,-0.157 0.04,-0.139 0.197,-0.026 0.134,-0.072 0.097,-0.131 0.181,-0.421 0.108,-0.452 0.01,-0.2 -0.142,-0.365 -0.112,-0.439 -0.003,-0.237 0.123,-0.274 0.176,-0.223 0.157,-0.052 0.17,-0.016 0.155,-0.086 0.144,-0.125 0.081,-0.138 0.126,-0.376 0.049,-0.214 -0.08,-0.576 0.082,-0.158 0.116,-0.098 0.155,0.074 0.16,0.015 0.186,-0.023 0.178,0.061 0.033,0.148 0.112,0.972 0.064,0.131 0.13,0.102 0.146,-0.015 0.126,-0.151 0.085,-0.201 0.168,-0.042 0.513,0.216 0.182,-0.154 0.118,-0.239 0.103,-0.423 -0.05,-0.382 -0.123,-0.142 -0.127,0.025 -0.112,0.105 -0.126,0.057 -0.757,0.201 0.004,-0.426 0.162,-0.64 0.089,-0.203 0.128,-0.096 0.318,0.112 0.155,0.074 0.339,0.318 z m -8.098,12.885 -0.267,0.009 -0.066,-0.035 0.161,-0.088 0.015,-0.147 0.097,-0.262 -0.002,-0.075 -0.212,-0.014 0.011,-0.297 0.158,-0.294 0.435,-0.463 0.119,-0.087 0.018,0.203 -0.132,0.479 -0.026,0.173 0.342,0.036 -0.22,0.573 -0.431,0.289 z m -13.958,5.664 -0.128,0.129 -0.24,-0.042 -0.139,-0.187 0.046,-0.211 0.251,-0.162 0.24,0.325 -0.03,0.148 z m 17.08,5.069 -0.03,0.16 -0.149,-0.035 -0.071,-0.104 0.009,-0.187 0.157,-0.001 0.084,0.167 z m -28.264,1.264 -0.057,0.163 -0.19,-0.115 -0.087,-0.104 0.177,-0.513 -0.021,-0.195 0.011,-0.095 0.351,-0.269 0.061,0.051 0.021,0.075 -0.031,0.115 0.018,0.254 -0.264,0.42 0.011,0.213 z m 15.569,0.221 -0.304,0.288 -0.264,-0.02 -0.132,-0.129 -0.044,-0.159 0.251,-0.25 0.216,-0.354 0.196,-0.157 0.158,-0.088 0.124,0.003 -0.278,0.494 0.077,0.372 z m -1.631,-0.661 -0.052,0.067 -0.05,-0.018 -0.179,0.155 -0.038,-0.149 -0.141,-0.099 -0.017,-0.078 0.403,-0.051 0.13,0.041 -0.056,0.132 z m 0.015,0.769 0.389,0.141 0.397,-0.04 -0.006,0.617 0.057,0.207 0.111,0.185 -0.057,0.269 0.18,0.092 -0.534,0.306 -0.481,0.406 -0.198,0.273 -0.179,0.293 -0.104,0.31 -0.067,0.333 -0.161,-0.132 -0.464,-0.541 -0.294,-0.148 -0.473,-0.079 -0.15,0.018 -0.972,0.505 -0.129,0.369 -0.265,0.555 -0.126,0.183 -0.14,0.053 -0.099,0.095 -0.108,0.472 -0.301,0.29 -0.185,0.009 -0.314,-0.08 -0.142,0.045 0.188,-0.465 -0.3,-0.057 -0.301,0.01 -0.007,-0.303 -0.182,-0.172 0.135,-0.224 0.004,-0.183 0.079,-0.101 0.027,-0.147 -0.011,-0.126 -0.185,-0.038 -0.113,-0.089 0.021,-0.332 -0.106,-0.012 -0.264,0.058 -0.548,0.256 -0.149,0 0.229,-0.183 0.487,-0.25 0.219,-0.144 0.478,-0.404 0.301,-0.191 0.156,-0.339 0.049,-0.206 0.102,-0.182 0.09,-0.291 0.154,-0.097 0.269,-0.25 0.154,0.024 0.172,0.307 0.231,0.235 0.166,-0.02 0.297,-0.121 0.144,-0.027 0.343,0.015 0.309,-0.149 0.126,-0.176 0.047,-0.22 -0.115,-0.369 0.148,0.037 0.143,-0.015 0.335,-0.235 0.345,-0.14 0.357,-0.035 0.402,0.133 0.389,0.212 z m -14.25,0.449 -0.183,0.137 -0.078,-0.209 0.08,-0.594 0.343,0.122 -0.006,0.182 -0.156,0.362 z m 9.258,0.028 -0.081,0.135 -0.249,-0.041 0.1,-0.117 0.076,-0.142 0.056,-0.029 0.047,0.154 0.051,0.04 z m -0.877,0.573 0.137,0.124 0.325,-0.05 0.04,0.035 -0.095,0.112 -0.144,0.111 -0.26,-0.083 -0.164,-0.004 -0.023,-0.185 0.021,-0.067 0.163,0.007 z m -3.062,1.151 0.377,0.1 0.16,0.006 0.147,-0.045 0.226,-0.131 0.235,-0.097 0.169,0.049 0.149,0.117 0.078,0.165 -0.038,0.172 -0.267,0.37 -0.22,0.394 0.504,0.074 0.504,-0.008 -0.117,0.243 -0.02,0.212 0.154,0.101 0.131,0.136 -0.034,0.123 -0.075,0.121 0.275,0.182 -0.018,0.122 -0.071,0.128 -0.687,0.834 -0.202,0.421 -0.14,0.463 -0.129,0.338 -0.094,0.351 -0.071,0.378 -0.128,0.39 0.043,0.345 -0.043,0.354 -0.345,0.872 -0.246,-0.016 -0.309,-0.105 -0.193,0.016 -0.1,0.193 0.177,0.397 -0.55,0.471 -0.608,0.316 -0.004,-0.144 0.058,-0.113 0.087,-0.091 0.063,-0.11 0.089,-0.37 -0.044,-0.373 -0.184,-0.468 -0.013,-0.168 0.127,-0.068 0.085,-0.02 0.046,-0.065 0.002,-0.155 -0.058,-0.115 -0.174,-0.037 -0.166,-0.002 -0.117,0.174 -0.161,0.335 -0.078,0.339 0.034,0.185 0.071,0.166 0.221,0.277 -0.064,0.164 -0.092,0.127 -0.78,-0.289 -0.169,-0.021 -0.14,-0.061 -0.15,-0.381 0.318,-0.092 0.094,-0.046 0.035,-0.122 0.043,-0.372 -0.148,-0.312 -0.126,-0.111 -0.102,-0.127 0.064,-0.263 -0.042,-0.332 -0.004,-0.464 0.055,-0.08 0.295,-0.094 0.213,-0.249 0.188,-0.284 0.275,-0.5 0.226,-0.541 -0.217,-0.023 -0.184,-0.102 0.2,-0.256 -0.062,-0.324 -0.3,-0.398 -0.165,-0.47 -0.265,-0.208 -0.14,-0.076 -0.171,0.11 -0.14,0.132 0.13,0.306 -0.016,0.271 0.021,0.268 0.132,0.015 0.163,-0.067 0.13,0.047 0.076,0.141 0.021,0.181 -0.058,0.179 -0.119,0.089 -0.146,-0.007 -0.147,-0.097 -0.115,-0.138 -0.275,-0.076 -0.29,0.163 -0.275,0.332 -0.235,0.168 0.11,-0.246 0.053,-0.266 -0.114,-0.187 -0.27,-0.311 -0.063,-0.18 -0.016,-0.218 0.048,-0.216 0.276,0.248 0.142,0.309 0.204,0.136 0.255,0.001 -0.196,-0.454 -0.07,-0.115 -0.274,-0.204 -0.376,-0.343 -0.238,-0.166 0.084,-0.359 0.141,-0.071 0.118,0.017 0.398,0.127 0.037,-0.179 -0.059,-0.096 -0.03,-0.111 0.263,-0.155 0.429,-0.128 0.088,-0.06 0.076,-0.129 0.105,-0.067 0.3,0.002 0.253,-0.124 0.209,-0.335 0.05,-0.184 0.074,-0.154 0.521,-0.272 0.129,-0.042 0.349,0.034 0.318,0.154 0.157,0.324 0.138,0.346 0.331,0.235 z m -3.87,-0.491 -0.194,0.139 -0.146,-0.108 0.071,-0.3 0.048,-0.1 0.166,0.099 0.055,0.27 z m -0.854,1.762 -0.197,0.157 -0.143,0 0.13,-0.184 0.018,-0.087 0.109,-0.247 0.213,-0.088 0.09,-0.011 -0.174,0.256 -0.046,0.204 z m -1.164,1.274 -0.07,0.036 -0.09,-0.3 -0.063,-0.107 0.105,-0.057 0.211,-0.545 0.038,0.216 0.082,0.214 0.082,0.034 -0.08,0.156 -0.117,0.058 -0.098,0.295 z m 30.21,-0.718 -0.049,0.035 -0.135,-0.109 -0.02,-0.097 0.024,-0.06 0.088,-0.013 0.182,0.119 -0.09,0.125 z m -31.365,0.906 0.109,0.09 0.159,-0.051 0.127,-0.012 0.091,0.043 0.115,0.231 0.042,0.137 -0.205,0.019 -0.087,0.032 -0.112,0.167 -0.161,-0.062 -0.101,-0.079 -0.022,-0.111 0.045,-0.404 z m 3.977,1.835 -0.222,0.118 -0.028,-0.113 -0.094,-0.052 0.161,-0.159 -0.006,-0.072 -0.102,-0.107 0.118,-0.406 -0.032,-0.175 0.443,-0.065 0.081,0.165 0.008,0.5 -0.327,0.366 z m 0.838,-0.641 -0.248,0.015 -0.103,-0.039 -0.041,-0.105 0.348,-0.213 0.27,0.038 -0.12,0.192 -0.106,0.112 z m -1.86,2.526 -0.088,0.057 0.056,-0.258 0.226,-0.226 0.019,0.146 -0.213,0.281 z m 3.484,4.107 -0.246,0.034 -0.005,-0.188 0.195,-0.424 0.021,-0.312 0.182,-0.394 0.077,-0.086 0.058,-0.031 0.063,0.123 -0.07,0.482 -0.183,0.365 -0.092,0.431 z m -0.945,0.433 -0.321,0.07 -0.176,-0.075 -0.162,-0.399 0.307,-0.25 0.41,0.248 0.084,0.071 -0.142,0.335 z m -3.284,6.573 -0.242,0.257 -0.257,-0.232 -0.31,-0.155 0.147,-0.042 0.086,-0.063 0.009,-0.098 0.201,-0.146 0.398,-0.113 0.127,-0.007 0.143,-0.106 0.047,-0.096 0.059,-0.046 0.257,-0.132 0.07,0.152 -0.012,0.119 -0.193,0.066 -0.188,0.159 -0.175,0.198 -0.156,0.084 -0.05,0.056 0.039,0.145 z m -0.361,0.33 0.019,0.074 -0.275,-0.062 -0.112,-0.289 0.183,0.052 0.056,0.099 0.129,0.126 z m -0.915,1.213 -0.118,0.058 -0.157,-0.08 -0.049,-0.362 0.07,-0.176 0.123,-0.039 0.107,0.313 0.074,0.129 -0.05,0.157 z m -2.075,3.352 -0.271,0.144 -0.1,0.171 -0.25,0.058 -0.243,0.24 -0.236,0.043 0.006,0.193 0.101,0.163 -0.157,0.029 -0.165,0.199 -0.013,0.145 0.059,0.116 -0.008,0.059 -0.208,0.172 -0.215,0.008 -0.009,-0.186 0.014,-0.139 0.203,-0.338 0.005,-0.393 0.188,-0.045 0.068,-0.055 0.297,-0.28 0.055,-0.119 -0.154,-0.116 0.012,-0.137 0.035,-0.058 0.244,0.044 0.099,0.102 0.049,0.011 0.143,-0.076 0.067,-0.136 0.266,-0.268 0.108,-0.266 0.215,0.218 -0.058,0.286 -0.147,0.211 z m 39.093,0.114 -0.052,0.002 -0.176,-0.331 0.051,-0.016 0.103,0.052 0.113,0.191 -0.039,0.102 z m -46.992,5.802 -0.237,0.08 -0.254,-0.047 0.041,-0.429 0.088,0.06 0.055,0.146 0.189,0.086 0.118,0.104 z m -3.231,0.698 -0.165,0.484 -0.137,0.07 -0.14,-0.039 -0.144,-0.27 0.101,-0.104 0.14,0.055 0.113,-0.021 0.257,-0.394 0.062,0.064 -0.087,0.155 z m -1.134,0.722 -0.177,0.043 -0.213,-0.053 -0.194,-0.015 -0.002,-0.091 0.203,-0.094 0.004,-0.131 0.05,-0.071 0.459,0.161 -0.02,0.118 -0.11,0.133 z"
  
end retData

★Click Here to Open This Script 

Posted in list Text | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | Leave a comment

ISOコードから国名を取得

Posted on 12月 30, 2019 by Takaaki Naganoya

ISOコード(ISO 3166-1 Alpha-2 code)で示した国の名称を取得するAppleScriptです。

現在のロケールでローカライズして取得するもの(retCountryNameInCurrentLocale)と、指定ロケールでローカライズするもの(retCountryNameInSpecifiedLocale)を用意しておきました。

Mac App Storeに出したDouble PDF v2.0(30言語以上ローカライズした)の審査は年越し確実で、審査に1か月以上かかるという、自分の知っている範囲での最長記録を更新しつつあります(AppleがOSに作ったバグを回避する以外の追加機能はわずかなのに)。

そんな中、各国語で国名を表記する方法を調べておきました。ヒンディー語、タイ語、ギリシア語あたりは文字が見慣れないながらもギリギリ文字単位での識別が可能で、非日常感があって(日本語の表記範囲で出てこない文字なので)クールな感じがします(個人の見解です)。アラビア語やヘブライ語になってしまうと、コンピュータの挙動が変わってしまうので(表記が右→左)、ちょっとシャレにならない感じであります。

AppleScript名:ISOコードから国名を取得.scpt
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/12/30
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

set aCountryName to retCountryNameInCurrentLocale("GE") of me
–> "ジョージア" —In Japanese (Current Locale, diffenret in each user)

set bCountryName to retCountryNameInSpecifiedLocale("GE", "en_US") of me
–> "Georgia" –In English
set cCountryName to retCountryNameInSpecifiedLocale("GE", "fr") of me
–> "Géorgie"–In French
set dCountryName to retCountryNameInSpecifiedLocale("GE", "ru") of me
–> "Грузия"–In Russian
set eCountryName to retCountryNameInSpecifiedLocale("GE", "zh") of me
–>"格鲁吉亚"–In Chinese
set fCountryName to retCountryNameInSpecifiedLocale("GE", "ko_KR") of me
–> "조지아"–In Korean
set gCountryName to retCountryNameInSpecifiedLocale("GE", "hi") of me
–> "जॉर्जिया" –In Hindi
set hCountryName to retCountryNameInSpecifiedLocale("GE", "th") of me
–> "จอร์เจีย"-In Thai
set iCountryName to retCountryNameInSpecifiedLocale("GE", "el_GR") of me
–> "Γεωργία"–In Greek

–指定の国名コードから国名を現在のロケールでローカライズして返す
on retCountryNameInCurrentLocale(isoCode as string)
  set curLocale to current application’s NSLocale’s currentLocale()
  
set aLocLangCode to (curLocale’s objectForKey:(current application’s NSLocaleLanguageCode)) as string
  
set aCountry to curLocale’s displayNameForKey:(current application’s NSLocaleCountryCode) value:isoCode
  
return aCountry as string
end retCountryNameInCurrentLocale

–指定の国名コードから国名を指定のロケールでローカライズして返す
on retCountryNameInSpecifiedLocale(isoCode as string, targLocale as string)
  set curLocale to current application’s NSLocale’s localeWithLocaleIdentifier:targLocale
  
set aLocLangCode to (curLocale’s objectForKey:(current application’s NSLocaleLanguageCode)) as string
  
set aCountry to curLocale’s displayNameForKey:(current application’s NSLocaleCountryCode) value:isoCode
  
return aCountry as string
end retCountryNameInSpecifiedLocale

★Click Here to Open This Script 

Posted in Language Locale | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSLocale NSLocaleCountryCode NSLocaleLanguageCode | Leave a comment

アラートダイアログをタイトル付き表示

Posted on 12月 27, 2019 by Takaaki Naganoya

アラートダイアログで、ウィンドウタイトルを表示させるAppleScriptです。

AppleScriptには登場当初からダイアログの表示命令「display dialog」が備わっていました。久しぶりにClassic MacOSのdisplay dialogコマンドの表示を見ると、あまりの素朴さに驚かされます。

display dialogは手軽であるもののモーダルなダイアログなので、その後のMac OS Xへの移行時にはいまひとつ合わない感じがしていました。完全にMac OS Xの流儀で書き直されたのが、「display alert」ダイアログです。こちらもモーダル表示ですが、見た目は少しMac OS Xらしく変更されました。

display alertは、さまざまなオプションを指定できる一方で手軽さがいまひとつで、やはりdisplay dialog命令のほうが圧倒的に利用されてきたという経緯があります(自分もほとんどdisplay alertは使いません)。

# display alertダイアログに表示されるボタンはTouchBarに表示されますが、display dialogダイアログ上のボタンはTouchBarには表示されません

非モーダル表示なUIについては、display notificationで通知表示が使えるようになり、これで一応の解決を見たというところでしょうか。こういう動作をする通知ダイアログは、Newt On Projectの中で「どうしても欲しい」という要望が出て、2000年代初頭にすでに仲間内で作ってもらったものがあり、AppleScriptから半透明のダイアログ(画面右側からスライドアニメーション表示)を表示させていました。

その一方で、display youtubeとかdisplay tableといった、ダイアログに各種GUI部品を詰め込んで簡易表示させるインタフェース「箱庭インタフェース」が今年局所的なブームを起こし、地図は表示させるわテーブルは表示させるわ、世界地図を表示して国選択を行わせるわで「計算結果を手軽に表示できたり、ファイルパスをわかりやすく選択できて便利」という評価をいただいています。

で、この「箱庭インタフェース」はもれなくalert dialogのインタフェースを用いています。display alertで表示されるものと同じGUI部品ですね。


▲HIGにサイコーに反していろいろいじくりまくっているpickup colorダイアログ。アイコン部分を色プレビュー領域に。でも、強烈に使いやすい

ちょっとした結果表示や項目選択のためにアラートダイアログ上にGUI部品を並べるやりかたは、「アリ」だと思っています。

そんな中、知り合い筋から「alertダイアログにタイトルは出せないのか?」と問い合わせがありました。アラートダイアログでタイトル表示が可能なことは知っていましたが、

Human Interface Guidelineに合わない仕様なので、タイトル表示は使ってきませんでした。

ただ、「箱庭インタフェース」シリーズでここまで無茶苦茶をやっておいて、いまさら他人に「HIGに反する」とかいっても説得力がまったくありません。

HIGのガイドラインに反するといっても、実際に使い勝手がよくなったり、顧客や上司からの無茶振りをかわすためであればアラートダイアログにタイトルを追加するというのも、アリなのかもしれません。自分はやりませんけれども。

AppleScript名:アラートダイアログをタイトル付き表示
— Created 2019-12-26 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"

property NSAlert : a reference to current application’s NSAlert
property NSRunningApplication : a reference to current application’s NSRunningApplication

property returnCode : 0

set paramObj to {myMessage:"アラート表示", mySubMessage:"アラートダイアログを表示します", myTitle:"たいとる?"}
set dRes to displayAlert(paramObj) of me

on displayAlert(paramObj)
  my performSelectorOnMainThread:"displayAlertDialog:" withObject:(paramObj) waitUntilDone:true
  
if (my returnCode as number) = 1001 then error number -128
  
return true
end displayAlert

on displayAlertDialog:paramObj
  set aMainMes to myMessage of paramObj
  
set aSubMes to mySubMessage of paramObj
  
set aTitle to myTitle of paramObj
  
  
— set up alert  
  
set theAlert to NSAlert’s alloc()’s init()
  
tell theAlert
    its setMessageText:aMainMes
    
its setInformativeText:aSubMes
    
its addButtonWithTitle:"OK"
    
–its addButtonWithTitle:"Cancel"
    
set myWin to its |window|
  end tell
  
  
myWin’s setTitle:aTitle
  
  
— show alert in modal loop
  
NSRunningApplication’s currentApplication()’s activateWithOptions:0
  
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
  
  
return (aScrollWithTable’s documentView’s selectedRow()) + 1
end displayAlertDialog:

on doModal:aParam
  set (my returnCode) to aParam’s runModal()
end doModal:

★Click Here to Open This Script 

Posted in dialog GUI | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy NSAlert NSRunningApplication | 2 Comments

アラートダイアログ上にTable Viewを表示 v8_ソート、並び替え、複数選択

Posted on 12月 25, 2019 by Takaaki Naganoya

アラートダイアログ上にTable Viewを表示するGUI部品を提供するAppleScriptです。Edama2さんから投稿していただいたものです。

箱庭テーブルビューシリーズは、macOS標準装備の「choose from list」コマンドでは選択肢が増えたときに使いにくいので、その代替品としてTable Viewを用いたポップアップしない単項目の選択UIを実装したものでした。


▲最初のバージョン。みなぎる使い捨て感

それが途中から「Myriad Tablesが使えない場面(Framework入りの高機能ライブラリのため、利用できないケースが発生)に使う使い捨て部品」に進化。

コードサイズの投げやりなまでの小ささと、いつもどおりのプレーンな読み味から改造のためのベースキットとして活用されまくり、派生品や亜種が内外でいろいろ発生しています(きっと知らないところで改変版が作られているはず)。

sdefをつけてライブラリ化したり、色付きダイアログなどいろいろキワモノが派生しましたが、実用性を考慮して半透明ウィンドウではなく通常ウィンドウとして表示する方向に変わりつつあります。

Version Author Date Description
v1 Piyomaru 2019/2/14 For choose from list without popup menu. One field selection UI.
v2 Piyomaru 2019/2/14
v3 Piyomaru 2019/2/14
v4 Piyomaru 2019/7/11 Table user interface for item selection
v5_e KniazidisR 2019/11/2 Separate display dialog stage into making and displaying
v5_m Piyomaru 2019/12/23 Filtering by multiple field
v6 Piyomaru 2019/12/24 Search Field Added
v7 Edama2 2019/12/240 Vertical & horizontal resizing
v8 Edama2 2019/12/25 Record sorting & Field re-ordering

以下、v8についてのedama2さんからの説明文です。

コラムのヘッダのクリックでテーブルのソート
ドラッグ&ドロップによる行の並び替え
行の複数選択

ができるようになりましたが、ヘッダのソート状態のときにD&Dの並び替えはできません。
飛び飛びに複数行選択しても並び替えできますが、たまにズレている気がします...(汗)

ArrayControllerを使用したのが機能過剰と思われたかもしれませんが、まずXCode上で一度組んだものを逆移植しているのでそんなに深い意味はないです。
でもソート方法を試行錯誤して調べていたら、Cocoa bindingをコーディングから設定できることがわかった(よく考えれば当たり前ですが)のが、何か壁を一枚破った気がしました。

Cocoa bindingがプログラムから動的に実行できることは、調査して知っていましたが、実際にAppleScriptのコードとして記述されたものは見たことがありませんでした(Mac Scripterのフォーラムを漁ると出てくるのかも?)。

### 表示内容をNSArrayControllerにバインディング
bind_toObject_withKeyPath_options_(current application’s NSValueBinding, my _data_source, "arrangedObjects." & aTitle, missing value)

ここの部分の記述は、クリスマスプレゼントとして楽しませていただきます。Cocoa Bindingなんて、Xcode上でGUI部品とイベント受信部分のハンドラとの接続をただ漫然とヒモでつなぐ作業をしていただけだったので、Cocoa Binding Referenceなんてはじめて細部にわたって眺めましたわー。


▲起動状態。フィールドの横サイズそろえ、レコード数により表UIの縦サイズが調整されている


▲Specsフィールドを中央に持ってきた。ちゃんとUIが細かいアニメーション動作を行う


▲Priceフィールドを先頭に移動させてみた


▲Priceでソートさせてみた


▲Specsでソートさせてみた


▲選択行をドラッグ&ドロップで移動。複数行も移動可能。ただし、フィールド指定のソート状態を有効にすると行移動が効かないという


▲Commandキーを押しながら複数行選択


▲ドラッグ&ドロップで移動


▲移動後

AppleScript名:アラートダイアログ上にTable Viewを表示 v8_ソート、並び替え、複数選択.scpt
on run
  
  
set aTableList to {}
  
set aTableList’s end to {|Name|:"MacBook Air", Price:"119,800円", Specs:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}
  
set aTableList’s end to {|Name|:"MacBook Pro 13", Price:"139,800円", Specs:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}
  
set aTableList’s end to {|Name|:"MacBook Pro 15", Price:"258,800円", Specs:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"Mac mini", Price:"122,800円", Specs:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"iMac 21.5", Price:"120,800円", Specs:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}
  
set aTableList’s end to {|Name|:"iMac 4K 21.5", Price:"142,800円", Specs:"3.6GHzクアッドコアIntel Core i3"}
  
set aTableList’s end to {|Name|:"iMac 5K 27", Price:"198,800円", Specs:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}
  
set optionRec to {aTableList:aTableList}
  
set optionRec to optionRec & {aSortOrder:{column1:"Name", column2:"Price", column3:"Specs"}}
  
  
set aMainMes to "項目の選択"
  
set aSubMes to "適切なものを以下からえらんでください"
  
set dateObj to my chooseData(aMainMes, aSubMes, optionRec)
end run

# アラートダイアログでtableviewを表示
on chooseData(aMainMes, aSubMes, optionRec)
  script MyDialog
    property parent : AppleScript
    
use AppleScript
    
use scripting additions
    
use framework "Foundation"
    
property _retrieve_data : missing value
    
on make
      set aClass to me
      
script
        property parent : aClass
      end script
    end make
    
## ダイアログの呼び出し
    
on call(aMainMes, aSubMes, optionRec)
      set paramObj to {myMessage:aMainMes, mySubMessage:aSubMes, myOption:optionRec}
      
parent’s performSelectorOnMainThread:"raize:" withObject:paramObj waitUntilDone:true
      
if (my _retrieve_data) is missing value then error number -128
      
return (my _retrieve_data)
    end call
    
## ダイアログの生成
    
on raize:paramObj
      ###
      
set mesText to paramObj’s myMessage
      
set infoText to paramObj’s mySubMessage
      
set paramObj to paramObj’s myOption
      
### set up view
      
set {theView, makeObj} to my makeContentView(paramObj)
      
### set up alert
      
tell current application’s NSAlert’s new()
        setMessageText_(mesText)
        
setInformativeText_(infoText)
        
addButtonWithTitle_("OK")
        
addButtonWithTitle_("Cancel")
        
setAccessoryView_(theView)
        
tell |window|()
          setInitialFirstResponder_(theView)
        end tell
        
#### show alert in modal loop
        
if runModal() is (current application’s NSAlertSecondButtonReturn) then return
      end tell
      
### retrieve date
      
my retrieveData(makeObj)
    end raize:
    
    
## ContentView を作成
    
property _data_source : missing value
    
property _data_type : (current date) as text –do shell script "uuidgen" –>ユニークな文字列ならなんでもいい?
    
on makeContentView(paramObj)
      ## 準備
      
set aList to (paramObj’s aTableList) as list
      
set keyRec to (paramObj’s aSortOrder) as record
      
set keyDict to (current application’s NSDictionary’s dictionaryWithDictionary:keyRec)
      
      
set my _data_source to current application’s NSArrayController’s new()
      
repeat with anItem in aList
        set aDict to (current application’s NSDictionary’s dictionaryWithDictionary:anItem)
        ((
my _data_source)’s addObject:aDict)
      end repeat
      (
my _data_source)’s setSelectionIndex:0
      
      
## NSTableView
      
tell current application’s NSTableView’s alloc()
        tell initWithFrame_(current application’s CGRectZero)
          setAllowsEmptySelection_(false)
          
setAllowsMultipleSelection_(true)
          
setDataSource_(me)
          
setDelegate_(me)
          
setDoubleAction_("doubleAction:")
          
setGridStyleMask_(current application’s NSTableViewSolidVerticalGridLineMask)
          
setSelectionHighlightStyle_(current application’s NSTableViewSelectionHighlightStyleRegular)
          
setTarget_(me)
          
setUsesAlternatingRowBackgroundColors_(true)
          
          
registerForDraggedTypes_({my _data_type})
          
setDraggingSourceOperationMask_forLocal_(current application’s NSDragOperationCopy, false)
          
          
set thisRowHeight to rowHeight() as integer
          
set aTableObj to it
        end tell
      end tell
      
      
## NSTableColumn
      
### Columnの並び順を指定する
      
set viewWidth to 0
      
set columnsCount to keyDict’s |count|()
      
repeat with colNum from 1 to columnsCount
        
        
set keyName to "column" & colNum as text
        
set aTitle to (keyDict’s objectForKey:keyName)
        
        
tell (current application’s NSTableColumn’s alloc()’s initWithIdentifier:(colNum as text))
          tell headerCell()
            setStringValue_(aTitle)
            
set thisHeaderHeight to cellSize()’s height
          end tell
          
          
### ソートの設定
          
set sortDescriptor to (current application’s NSSortDescriptor’s sortDescriptorWithKey:aTitle ascending:true selector:"compare:")
          
setSortDescriptorPrototype_(sortDescriptor)
          
          
### 表示内容をNSArrayControllerにバインディング
          
bind_toObject_withKeyPath_options_(current application’s NSValueBinding, my _data_source, "arrangedObjects." & aTitle, missing value)
          
          
set aTableColumn to it
        end tell
        
        
### Columnの横幅を調整
        
tell aTableObj
          addTableColumn_(aTableColumn)
          
–reloadData()
          
set colWidthMax to 0
          
set rowCount to numberOfRows()
          
          
repeat with rowNum from 1 to rowCount
            tell preparedCellAtColumn_row_(colNum – 1, rowNum – 1)
              set thisWidthSize to cellSize()’s width
              
–log result
              
if thisWidthSize is greater than or equal to colWidthMax then set colWidthMax to thisWidthSize
            end tell
          end repeat
        end tell
        
–log colWidthMax
        
        
set colWidthMax to colWidthMax + 5 –> 5は余白
        
tell aTableColumn
          setWidth_(colWidthMax)
        end tell
        
        
set viewWidth to viewWidth + colWidthMax
      end repeat
      
      
## NSScrollView
      
### Viewの高さを計算
      
set viewHeight to (thisRowHeight + 2) * rowCount + thisHeaderHeight –> 2を足さないと高さが合わない
      
set vSize to current application’s NSMakeRect(0, 0, viewWidth + 10, viewHeight) –> 10を足すといい感じの横幅になる
      
      
### Viewを作成
      
tell current application’s NSScrollView’s alloc()
        tell initWithFrame_(vSize)
          setBorderType_(current application’s NSBezelBorder)
          
setDocumentView_(aTableObj)
          
–setHasHorizontalScroller_(true)
          
–setHasVerticalScroller_(true)
          
set aScroll to it
        end tell
      end tell
      
      
return {aScroll, aTableObj}
    end makeContentView
    
    
## retrieve date
    
on retrieveData(aTableObj)
      set aIndexSet to aTableObj’s selectedRowIndexes()
      
set my _retrieve_data to ((my _data_source)’s arrangedObjects()’s objectsAtIndexes:aIndexSet) as list –setSelectionIndexes:aIndexSet
      
log result
    end retrieveData
    
    
    
# NSTableViewDatasource
    
on numberOfRowsInTableView:aTableView
      –log "numberOfRowsInTableView:"
      
return (my _data_source)’s content()’s |count|()
    end numberOfRowsInTableView:
    
# NSTableViewDelegate
    
on tableView:aTableView objectValueForTableColumn:aColumn row:aRow
    
end tableView:objectValueForTableColumn:row:
    
# テーブル内のセルが編集できるか
    
on tableView:aTableView shouldEditTableColumn:aColumn row:aRow
      return false
    end tableView:shouldEditTableColumn:row:
    
# テーブル内をダブルクリックしたらOKボタンを押す
    
on doubleAction:sender
      –log "doubleAction"
      
–log sender’s |className|() as text
      
## ヘッダをクリックした時は何もしない
      
if (sender’s clickedRow()) is -1 then return
      
      
set theEvent to current application’s NSEvent’s ¬
        keyEventWithType:(current application’s NSEventTypeKeyDown) ¬
          location:(current application’s NSZeroPoint) ¬
          
modifierFlags:0 ¬
          
timestamp:0.0 ¬
          
windowNumber:(sender’s |window|()’s windowNumber()) ¬
          
context:(current application’s NSGraphicsContext’s currentContext()) ¬
          
|characters|:return ¬
          
charactersIgnoringModifiers:(missing value) ¬
          
isARepeat:false ¬
          
keyCode:0
      current application’s NSApp’s postEvent:theEvent atStart:(not false)
    end doubleAction:
    
    
# Drag Operation Method
    
## ドラッグを開始(ペーストボードに書き込む)
    
on tableView:aTableView writeRowsWithIndexes:rowIndexes toPasteboard:pboard
      –log "writeRowsWithIndexes"
      
set aData to current application’s NSKeyedArchiver’s archivedDataWithRootObject:rowIndexes
      
pboard’s declareTypes:{my _data_type} owner:(missing value)
      
pboard’s setData:aData forType:(my _data_type)
      
return true
    end tableView:writeRowsWithIndexes:toPasteboard:
    
## ドラッグ途中
    
on tableView:aTableView validateDrop:info proposedRow:row proposedDropOperation:operation
      –log "validateDrop"
      
### 列の間にドラッグ
      
if (operation is current application’s NSTableViewDropAbove) then
        return current application’s NSDragOperationMove
      end if
      
### 項目の上にドラッグ
      
set aTypes to info’s draggingPasteboard’s types()
      
if (aTypes’s containsObject:(my _data_type)) as boolean then
        return current application’s NSDragOperationNone
      end if
      
return current application’s NSDragOperationNone
    end tableView:validateDrop:proposedRow:proposedDropOperation:
    
## ドラッグ終了
    
on tableView:aTableView acceptDrop:info row:row dropOperation:operation
      –log "acceptDrop"
      
set pboard to info’s draggingPasteboard()
      
      
set rowData to pboard’s dataForType:(my _data_type)
      
set rowIndexes to current application’s NSKeyedUnarchiver’s unarchiveObjectWithData:rowData
      
      
if (rowIndexes’s firstIndex()) < row then
        set row to row – (rowIndexes’s |count|())
      end if
      
      
set aRange to current application’s NSMakeRange(row, rowIndexes’s |count|())
      
set aIndexSet to current application’s NSIndexSet’s indexSetWithIndexesInRange:aRange
      
      
tell my _data_source
        set anObj to content()’s objectsAtIndexes:rowIndexes
        
removeObjects_(anObj)
        
insertObjects_atArrangedObjectIndexes_(anObj, aIndexSet)
        
rearrangeObjects()
      end tell
      
return true
    end tableView:acceptDrop:row:dropOperation:
  end script
  
  
##
  
tell (make MyDialog)
    return call(aMainMes, aSubMes, optionRec)
  end tell
end chooseData

★Click Here to Open This Script 

Posted in dialog GUI | Tagged 10.13savvy 10.14savvy 10.15savvy | Leave a comment

アラートダイアログ上にTable Viewを表示 v7_サイズ調整あり

Posted on 12月 24, 2019 by Takaaki Naganoya

先日「macOS Native」のイベント後に秋葉原で顔見知りのScripter3人でカレー食べて帰ってきました。その際に、アラートダイアログ上に作成した箱庭User Interface類の話で盛り上がっていました。「意外と使える」「自分でもいろいろ作ってる」「公開してよ」といったような。

本Scriptはその際の話を受けてEdama2さんが作っている試作品の、さらに試作品になるわけですが、プログラム内容が自分とは別の価値体系で清書し直されており、あいかわらずロジックとコードの美しさにうならされます。また、「本来倒すべき敵」に向けての実装が行われているので、単にテーブルビューを表示するだけには少々機能過剰になっています。

以下、Edama2さんによる投稿内容です。

タイトルは「アラートダイアログ上にTable Viewを表示 v7_サイズ調整あり」

主な変更点は
表示する内容に合わせてviewのサイズを調整
レコードのラベルをヘッダのタイトルにする
Table ViewをダブルクリックするとOKボタンを押す
setAllowsEmptySelection: をfalseにして1行目を選択するようにした

データ作成部分が詰め込み効率優先ではなく可読性を高めた作りになっているのが、Edama2さんらしいところです。また、tellブロックをCocoa Scriptingにも多用しているのも特徴です。

ロジックが読みやすい一方で、Cocoa Framework相手にここまで見やすく書くのは、相当の努力が必要なはずで、Cocoa Scripting時に省いてしまいがちな「清書」という1手間が入っていることを感じさせます。

本Scriptはハンドラ(サブルーチン)が前の方に配置される記法です。AppleScriptはもともとハンドラ宣言部を前に書く言語なので、世界的に見るとこちらが主流です(Shane Stanleyですらハンドラ宣言部は前に書きます)。逆に、自分が他の言語に合わせてハンドラ宣言部を後ろに配置するのは、全体から見ると異端といえます(他の言語と書き方が違いすぎるのはどうかと思って、ハンドラ宣言部を後ろに書いています)。

たしかに、自分の箱庭テーブルビューダイアログではカラム幅とテーブルの縦サイズは一切手をつけていなかったので、縦横幅高さの自動調整が入ると、格段に見やすくなります。

Cocoaの機能を呼び出すAppleScriptにおいても、書きこなれてきたことによりハンドラ内にScript文を書いてさらに内部にハンドラを記述するといったような、論理分割やら階層構造化が本Scriptにおいて多用されています。そのあたり、applescript-stdlib(2015)で見かけましたが、本Scriptのように控えめな利用だと安心できます。

本Script内には継続記号(「¬」)が多用されていますが、macOS日本語ユーザー環境上でScript Debuggerを使っていると、構文確認時にこれがひっかかってエラーになることがあります(というか、実際にウチでこれを編集してなっています)。継続記号がひっかかって構文確認(コンパイル)できないようであれば、いっそ継続記号をすべて削除すべきでしょう。継続記号に「可読性を上げる」以外の機能はないため、削除しても無害です。

AppleScript名:アラートダイアログ上にTable Viewを表示 v7_サイズ調整あり.scpt
on run
  
  
set aTableList to {}
  
set aTableList’s end to {|Name|:"MacBook Air", Price:"119,800円", Specs:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}
  
set aTableList’s end to {|Name|:"MacBook Pro 13", Price:"139,800円", Specs:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}
  
set aTableList’s end to {|Name|:"MacBook Pro 15", Price:"258,800円", Specs:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"Mac mini", Price:"122,800円", Specs:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"iMac 21.5", Price:"120,800円", Specs:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}
  
set aTableList’s end to {|Name|:"iMac 4K 21.5", Price:"142,800円", Specs:"3.6GHzクアッドコアIntel Core i3"}
  
set aTableList’s end to {|Name|:"iMac 5K 27", Price:"198,800円", Specs:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}
  
set optionRec to {aTableList:aTableList}
  
set optionRec to optionRec & {aSortOrder:{column1:"Name", column2:"Price", column3:"Specs"}}
  
  
set aMainMes to "項目の選択"
  
set aSubMes to "適切なものを以下からえらんでください"
  
set dateObj to my chooseData(aMainMes, aSubMes, optionRec)
end run

# アラートダイアログでtableviewを表示
on chooseData(aMainMes, aSubMes, optionRec)
  script MyDialog
    property parent : AppleScript
    
use AppleScript
    
use scripting additions
    
use framework "Foundation"
    
property _retrieve_data : missing value
    
on make
      set aClass to me
      
script
        property parent : aClass
      end script
    end make
    
## ダイアログの呼び出し
    
on call(aMainMes, aSubMes, optionRec)
      set paramObj to {myMessage:aMainMes, mySubMessage:aSubMes, myOption:optionRec}
      
parent’s performSelectorOnMainThread:"raize:" withObject:paramObj waitUntilDone:true
      
if (my _retrieve_data) is missing value then error number -128
      
return (my _retrieve_data)
    end call
    
## ダイアログの生成
    
on raize:paramObj
      ###
      
set mesText to paramObj’s myMessage
      
set infoText to paramObj’s mySubMessage
      
set paramObj to paramObj’s myOption
      
### set up view
      
set {theView, makeObj} to my makeContentView(paramObj)
      
### set up alert
      
tell current application’s NSAlert’s new()
        setMessageText_(mesText)
        
setInformativeText_(infoText)
        
addButtonWithTitle_("OK")
        
addButtonWithTitle_("Cancel")
        
setAccessoryView_(theView)
        
tell |window|()
          setInitialFirstResponder_(theView)
        end tell
        
#### show alert in modal loop
        
if runModal() is (current application’s NSAlertSecondButtonReturn) then return
      end tell
      
### retrieve date
      
my retrieveData(makeObj)
    end raize:
    
    
## ContentView を作成
    
property _data_source : missing value
    
on makeContentView(paramObj)
      ## 準備
      
set aList to (paramObj’s aTableList) as list
      
set keyRec to (paramObj’s aSortOrder) as record
      
set keyDict to (current application’s NSDictionary’s dictionaryWithDictionary:keyRec)
      
      
set my _data_source to current application’s NSArrayController’s new()
      
repeat with anItem in aList
        set aDict to (current application’s NSDictionary’s dictionaryWithDictionary:anItem)
        ((
my _data_source)’s addObject:aDict)
      end repeat
      
      
## NSTableView
      
tell current application’s NSTableView’s alloc()
        tell initWithFrame_(current application’s CGRectZero)
          setAllowsEmptySelection_(false)
          
setDataSource_(me)
          
setDelegate_(me)
          
setDoubleAction_("doubleAction:")
          
setGridStyleMask_(current application’s NSTableViewSolidVerticalGridLineMask)
          
setSelectionHighlightStyle_(current application’s NSTableViewSelectionHighlightStyleRegular)
          
setTarget_(me)
          
setUsesAlternatingRowBackgroundColors_(true)
          
          
set thisRowHeight to rowHeight() as integer
          
set aTableObj to it
        end tell
      end tell
      
      
## NSTableColumn
      
### Columnの並び順を指定する
      
set viewWidth to 0
      
set columnsCount to keyDict’s |count|()
      
repeat with colNum from 1 to columnsCount
        
        
set keyName to "column" & colNum as text
        
set aTitle to (keyDict’s objectForKey:keyName)
        
        
tell (current application’s NSTableColumn’s alloc()’s initWithIdentifier:(colNum as text))
          tell headerCell()
            setStringValue_(aTitle)
            
set thisHeaderHeight to cellSize()’s height
          end tell
          
          
set aTableColumn to it
        end tell
        
        
### Columnの横幅を調整
        
tell aTableObj
          addTableColumn_(aTableColumn)
          
–reloadData()
          
set colWidthMax to 0
          
set rowCount to numberOfRows()
          
          
repeat with rowNum from 1 to rowCount
            tell preparedCellAtColumn_row_(colNum – 1, rowNum – 1)
              set thisWidthSize to cellSize()’s width
              
–log result
              
if thisWidthSize is greater than or equal to colWidthMax then set colWidthMax to thisWidthSize
            end tell
          end repeat
        end tell
        
–log colWidthMax
        
        
set colWidthMax to colWidthMax + 5 –> 5は余白
        
tell aTableColumn
          setWidth_(colWidthMax)
        end tell
        
        
set viewWidth to viewWidth + colWidthMax
      end repeat
      
      
## NSScrollView
      
### Viewの高さを計算
      
set viewHeight to (thisRowHeight + 2) * rowCount + thisHeaderHeight –> 2を足さないと高さが合わない
      
set vSize to current application’s NSMakeRect(0, 0, viewWidth + 10, viewHeight) –> 10を足すといい感じの横幅になる
      
      
### Viewを作成
      
tell current application’s NSScrollView’s alloc()
        tell initWithFrame_(vSize)
          setBorderType_(current application’s NSBezelBorder)
          
setDocumentView_(aTableObj)
          
–setHasHorizontalScroller_(true)
          
–setHasVerticalScroller_(true)
          
set aScroll to it
        end tell
      end tell
      
      
return {aScroll, aTableObj}
    end makeContentView
    
    
## retrieve data
    
on retrieveData(aTableObj)
      set aRow to aTableObj’s selectedRow()
      
log result
      
if aRow is -1 then
        set my _retrieve_data to {}
      else
        set my _retrieve_data to ((my _data_source)’s arrangedObjects()’s objectAtIndex:aRow) as record
      end if
    end retrieveData
    
    
    
# NSTableViewDatasource
    
on numberOfRowsInTableView:aTableView
      –log "numberOfRowsInTableView:"
      
return (my _data_source)’s content()’s |count|()
    end numberOfRowsInTableView:
    
# NSTableViewDelegate
    
on tableView:aTableView objectValueForTableColumn:aColumn row:aRow
      –log "objectValueForTableColumn"
      
set keyName to aColumn’s headerCell()’s title()
      
set aDict to (my _data_source)’s arrangedObjects()’s objectAtIndex:aRow
      
set aStr to aDict’s objectForKey:keyName
      
–log result as text
      
return aStr
    end tableView:objectValueForTableColumn:row:
    
# テーブル内のセルが編集できるか
    
on tableView:aTableView shouldEditTableColumn:aColumn row:aRow
      return false
    end tableView:shouldEditTableColumn:row:
    
# テーブル内をダブルクリックしたらOKボタンを押す
    
on doubleAction:sender
      –log "doubleAction"
      
–log sender’s |className|() as text
      
set theEvent to current application’s NSEvent’s ¬
        keyEventWithType:(current application’s NSEventTypeKeyDown) ¬
          location:(current application’s NSZeroPoint) ¬
          
modifierFlags:0 ¬
          
timestamp:0.0 ¬
          
windowNumber:(sender’s |window|()’s windowNumber()) ¬
          
context:(current application’s NSGraphicsContext’s currentContext()) ¬
          
|characters|:return ¬
          
charactersIgnoringModifiers:(missing value) ¬
          
isARepeat:false ¬
          
keyCode:0
      current application’s NSApp’s postEvent:theEvent atStart:(not false)
    end doubleAction:
  end script
  
  
##
  
tell (make MyDialog)
    return call(aMainMes, aSubMes, optionRec)
  end tell
end chooseData

★Click Here to Open This Script 

Posted in dialog GUI | Tagged 10.13savvy 10.14savvy 10.15savvy | 1 Comment

アラートダイアログ上にTable Viewを表示 v6_サーチフィールドつき

Posted on 12月 24, 2019 by Takaaki Naganoya

検索フィールドつきのTable View表示ダイアログを表示するAppleScriptです。項目選択を行う簡易ユーザーインタフェース(ダイアログ)で、選択肢の数が多い場合に備えて項目のキーワード抽出機能を付加したものです。

サーチフィールドの実装は無理かと思っていたのですが、単体でアラートダイアログ上に表示してみたら、予想外にキーボード入力イベントと検索語のクリアのイベントを簡単に拾えたので、Table Viewと組み合わせて試してみました。

AppleScript名:アラートダイアログ上にTable Viewを表示 v6_サーチフィールドつき
— Created 2019-12-23 by Takaaki Naganoya
— 2019 Piyomaru Software
set aRes to displayCondTable() of filterTableDialogView
–> {field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)", field2:198800, field1:"iMac 5K 27"}

script filterTableDialogView
  use scripting additions
  
use framework "Foundation"
  
use framework "AppKit"
  
property parent : AppleScript
  
  
property NSView : a reference to current application’s NSView
  
property NSAlert : a reference to current application’s NSAlert
  
property NSIndexSet : a reference to current application’s NSIndexSet
  
property NSPredicate : a reference to current application’s NSPredicate
  
property NSScrollView : a reference to current application’s NSScrollView
  
property NSTableView : a reference to current application’s NSTableView
  
property NSSearchField : a reference to current application’s NSSearchField
  
property NSTableColumn : a reference to current application’s NSTableColumn
  
property NSMutableArray : a reference to current application’s NSMutableArray
  
property NSRunningApplication : a reference to current application’s NSRunningApplication
  
property NSModalPanelWindowLevel : a reference to current application’s NSModalPanelWindowLevel
  
  
property theResult : 0
  
property returnCode : 0
  
property theDataSource : {}
  
property tView : missing value
  
property aDataList : {}
  
  
  
on displayCondTable()
    set (my theResult) to 0 –initialize
    
    
set aDataList to {{field1:"MacBook Air", field2:119800, field3:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}, {field1:"MacBook Pro 13", field2:139800, field3:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}, {field1:"MacBook Pro 15", field2:258800, field3:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}, {field1:"Mac mini", field2:122800, field3:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}, {field1:"iMac 21.5", field2:120800, field3:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}, {field1:"iMac 4K 21.5", field2:142800, field3:"3.6GHzクアッドコアIntel Core i3"}, {field1:"iMac 5K 27", field2:198800, field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}, {field1:"iMac Pro", field2:558800, field3:"3.2GHz Intel Xeon W Turbo Boost使用時最大4.2GHz 19MBキャッシュ"}, {field1:"Mac Pro 2019", field2:599800, field3:"3.5GHz 8コアIntel Xeon Wプロセッサ(Turbo Boost使用時最大4.0GHz)"}}
    
    
set paramObj to {myMessage:"項目の選択", mySubMessage:"適切なものを以下からえらんでください", aTableList:aDataList, aSortOrder:{"field1", "field2", "field3"}}
    
    
–my chooseItemByTableView:paramObj –for debug
    
my performSelectorOnMainThread:"chooseItemByTableView:" withObject:paramObj waitUntilDone:true
    
    
return (my theResult)
  end displayCondTable
  
  
  
  
on chooseItemByTableView:paramObj
    set aMainMes to myMessage of paramObj
    
set aSubMes to mySubMessage of paramObj
    
set aTList to (aTableList of paramObj) as list
    
set labelSortList to (aSortOrder of paramObj) as list
    
    
set aWidth to 800
    
set aHeight to 300
    
    
–Viewをつくる
    
set parentView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
    
set aTextInput to makeNSSearchField(0, aHeight – 20, 300, 20) of me
    
    
    
set aScroll to makeTableView(aTList, aWidth, aHeight – 80, labelSortList) of me
    
    
parentView’s setSubviews:{aTextInput, aScroll}
    
    
— set up alert  
    
set theAlert to NSAlert’s alloc()’s init()
    
tell theAlert
      its setMessageText:aMainMes
      
its setInformativeText:aSubMes
      
its addButtonWithTitle:"OK"
      
its addButtonWithTitle:"Cancel"
      
its setAccessoryView:(parentView)
      
      
set myWindow to its |window|
    end tell
    
    
myWindow’s setLevel:(NSModalPanelWindowLevel)
    
    
— show alert in modal loop
    
NSRunningApplication’s currentApplication()’s activateWithOptions:0
    
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
    
if (my returnCode) = 1001 then error number -128
    
    
set tmpResult to (aScroll’s documentView’s selectedRow()) + 1
    
set (my theResult) to contents of item tmpResult of ((my theDataSource) as list)
  end chooseItemByTableView:
  
  
  
on doModal:aParam
    set (my returnCode) to (aParam’s runModal()) as number
  end doModal:
  
  
  
  
  
–TableView Event Handlers
  
on numberOfRowsInTableView:aView
    return (my theDataSource)’s |count|()
  end numberOfRowsInTableView:
  
  
  
on tableView:aView objectValueForTableColumn:aColumn row:aRow
    set aRec to (my theDataSource)’s objectAtIndex:(aRow as number)
    
set aTitle to (aColumn’s headerCell()’s title()) as string
    
set aRes to (aRec’s valueForKey:aTitle)
    
return aRes
  end tableView:objectValueForTableColumn:row:
  
  
  
  
on makeTableView(aDicList, aWidth, aHeight, labelSortList)
    set aOffset to 40
    
set theDataSource to NSMutableArray’s alloc()’s init()
    
theDataSource’s addObjectsFromArray:aDicList
    
    
–TextField
    
set aTextInput to makeNSSearchField(0, 0, 300, 20) of me
    
    
set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight))
    
set tView to NSTableView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight))
    
    
set aLen to length of labelSortList
    
    
repeat with i in labelSortList
      set j to contents of i
      
set aColumn to (NSTableColumn’s alloc()’s initWithIdentifier:j)
      (
aColumn’s setWidth:(aWidth div aLen))
      (
aColumn’s headerCell()’s setStringValue:j)
      (
tView’s addTableColumn:aColumn)
    end repeat
    
    
tView’s setDelegate:me
    
tView’s setDataSource:me
    
tView’s reloadData()
    
    
aScroll’s setDocumentView:tView
    
tView’s enclosingScrollView()’s setHasVerticalScroller:true
    
aScroll’s setVerticalLineScroll:(30.0 as real)
    
    
–1行目を選択
    
set aIndexSet to NSIndexSet’s indexSetWithIndex:0
    
tView’s selectRowIndexes:aIndexSet byExtendingSelection:false
    
    
–強制的にトップにスクロール
    
set aDBounds to aScroll’s documentView()’s |bounds|()
    
if class of aDBounds = list then
      –macOS 10.13 or later
      
set maxHeight to item 2 of item 1 of aDBounds
    else
      –macOS 10.10….10.12
      
set maxHeight to height of |size| of aDBounds
    end if
    
    
set aPT to current application’s NSMakePoint(0.0, -1 * (maxHeight as real))
    
aScroll’s documentView()’s scrollPoint:aPT
    
    
return aScroll
  end makeTableView
  
  
  
on alertShowHelp:aNotification
    display dialog "Help Me!" buttons {"OK"} default button 1 with icon 1
    
return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする
  end alertShowHelp:
  
  
  
on makeNSSearchField(xPos as integer, yPos as integer, myWidth as integer, myHeight as integer)
    set aSearchF to NSSearchField’s alloc()’s initWithFrame:(current application’s NSMakeRect(xPos, yPos, myWidth, myHeight))
    
aSearchF’s setDelegate:(me)
    
return aSearchF
  end makeNSSearchField
  
  
  
–検索クエリ入力時
  
on searchFieldDidStartSearching:(aField)
    set aStr to (aField’s stringValue()) as string
    
set predicStr to "field1 contains[cd] ’" & aStr & "’ OR field3 contains[cd] ’" & aStr & "’"
    
set filteredArray to filterRecListByLabel1((my aDataList), predicStr) of me
    
set (my theDataSource) to filteredArray
    
tView’s reloadData()
  end searchFieldDidStartSearching:
  
  
  
–Search Fieldの「x」ボタンを押したイベント
  
on searchFieldDidEndSearching:(aField)
    set (my theDataSource) to NSMutableArray’s arrayWithArray:(my aDataList)
    
tView’s reloadData()
  end searchFieldDidEndSearching:
  
  
  
–リストに入れたレコードを、指定の属性ラベルの値で抽出
  
on filterRecListByLabel1(aRecList as list, aPredicate as string)
    set aArray to NSMutableArray’s arrayWithArray:aRecList
    
set aPredicate to NSPredicate’s predicateWithFormat:aPredicate
    
set filteredArray to aArray’s filteredArrayUsingPredicate:aPredicate
    
return filteredArray
  end filterRecListByLabel1
  
end script

★Click Here to Open This Script 

Posted in dialog GUI | Tagged 10.13savvy 10.14savvy 10.15savvy NSAlert NSIndexSet NSModalPanelWindowLevel NSMutableArray NSPredicate NSRunningApplication NSScrollView NSSearchField NSTableColumn NSTableView NSView | 8 Comments

アラートダイアログ上にTable Viewを表示 v5_複数キー抽出つき

Posted on 12月 23, 2019 by Takaaki Naganoya

アラートダイアログ上にTableViewを表示し、複数キーの組み合わせによって項目抽出。選択項目のデータを返すAppleScriptです。

あくまで試作品なので、あちらこちらに「お可愛らしい」実装が転がっています。NSBoxがまだまともに使いこなせていないあたりとか(Xcode上で部品として配置するのは楽勝ですが、プログラムから動的に生成して使用するのは別なので)。

抽出キー数は可変で外部から指定できるとよいのですが、本Scriptでは固定です。また、各抽出条件も外部から供給するのが本来あるべき姿ですが、ハードコーディングしています。

あと、TableViewの下側に謎の余白があるのは、めんどくさくなってそのまま放置しています。これで外部から各種パラメータを指定できるようにして、sdefつけて1命令で呼び出せるようにしておけば、レコード数の多い選択項目から条件抽出しつつ項目選択できてよいでしょう。

プログラム内容自体は、高度でもなければ高尚でもありません。実にダラダラとGUI部品のパラメータを設定しているだけです。

AppleScript名:アラートダイアログ上にTable Viewを表示 v5_複数キー抽出つき
— Created 2019-12-22 by Takaaki Naganoya
— 2019 Piyomaru Software
set aRes to displayCondTable() of filterTableDialogView
–> {field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)", field2:198800, field1:"iMac 5K 27"}

script filterTableDialogView
  use scripting additions
  
use framework "Foundation"
  
use framework "AppKit"
  
property parent : AppleScript
  
  
property NSBox : a reference to current application’s NSBox
  
property NSView : a reference to current application’s NSView
  
property NSAlert : a reference to current application’s NSAlert
  
property NSColor : a reference to current application’s NSColor
  
property NSIndexSet : a reference to current application’s NSIndexSet
  
property NSPredicate : a reference to current application’s NSPredicate
  
property NSScrollView : a reference to current application’s NSScrollView
  
property NSTableView : a reference to current application’s NSTableView
  
property NSTableColumn : a reference to current application’s NSTableColumn
  
property NSPopUpButton : a reference to current application’s NSPopUpButton
  
property NSMutableArray : a reference to current application’s NSMutableArray
  
property NSRunningApplication : a reference to current application’s NSRunningApplication
  
property NSCompoundPredicate : a reference to current application’s NSCompoundPredicate
  
property NSModalPanelWindowLevel : a reference to current application’s NSModalPanelWindowLevel
  
property NSAlertSecondButtonReturn : a reference to current application’s NSAlertSecondButtonReturn
  
  
  
property theResult : 0
  
property returnCode : 0
  
property theDataSource : {}
  
property tView : missing value
  
property aDataList : {}
  
property aSel : 0
  
property bSel : 0
  
property cSel : 0
  
property predList : {}
  
property a1Button : missing value
  
property a2Button : missing value
  
property a3Button : missing value
  
  
on displayCondTable()
    set (my theResult) to 0 –initialize
    
    
set aDataList to {{field1:"MacBook Air", field2:119800, field3:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}, {field1:"MacBook Pro 13", field2:139800, field3:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}, {field1:"MacBook Pro 15", field2:258800, field3:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}, {field1:"Mac mini", field2:122800, field3:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}, {field1:"iMac 21.5", field2:120800, field3:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}, {field1:"iMac 4K 21.5", field2:142800, field3:"3.6GHzクアッドコアIntel Core i3"}, {field1:"iMac 5K 27", field2:198800, field3:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}, {field1:"iMac Pro", field2:558800, field3:"3.2GHz Intel Xeon W Turbo Boost使用時最大4.2GHz 19MBキャッシュ"}, {field1:"Mac Pro 2019", field2:599800, field3:"3.5GHz 8コアIntel Xeon Wプロセッサ(Turbo Boost使用時最大4.0GHz)"}}
    
    
set paramObj to {myMessage:"項目の選択", mySubMessage:"適切なものを以下からえらんでください", aTableList:aDataList, aSortOrder:{"field1", "field2", "field3"}}
    
    
–my chooseItemByTableView:paramObj –for debug
    
my performSelectorOnMainThread:"chooseItemByTableView:" withObject:paramObj waitUntilDone:true
    
    
return (my theResult)
  end displayCondTable
  
  
on chooseItemByTableView:paramObj
    set aMainMes to myMessage of paramObj
    
set aSubMes to mySubMessage of paramObj
    
set aTList to (aTableList of paramObj) as list
    
set labelSortList to (aSortOrder of paramObj) as list
    
    
set aWidth to 800
    
set aHeight to 400
    
set my aSel to 0
    
set my bSel to 0
    
    
–Viewをつくる
    
set parentView to NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
    
    
    
–BOX Aをつくる
    
set aBox to (NSBox’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aHeight – 60, aWidth, 60)))
    (
aBox’s setTitle:("Filter Condition"))
    
    
–このあたり、項目数に合わせてUIを可変で生成するように(本Scriptは試作品なので、決め打ちでUI生成)
    
set a1Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 200, 30)) pullsDown:false)
    
a1Button’s removeAllItems()
    (
a1Button’s addItemsWithTitles:{"▼Select Item", "MacBook", "iMac", "mini", "Air", "Pro"})
    
a1Button’s setTarget:(me)
    
a1Button’s setAction:("mySelector:")
    
a1Button’s setEnabled:(true)
    
    
set a2Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(220, 0, 200, 30)) pullsDown:false)
    
a2Button’s removeAllItems()
    (
a2Button’s addItemsWithTitles:{"▼Select Item", "150000", "200000", "300000", "400000", "600000"})
    
a2Button’s setTarget:(me)
    
a2Button’s setAction:("mySelector:")
    
a2Button’s setEnabled:(true)
    
    
set a3Button to (NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(440, 0, 200, 30)) pullsDown:false)
    
a3Button’s removeAllItems()
    (
a3Button’s addItemsWithTitles:{"▼Select Item", "デュアルコア", "クアッドコア", "6コア", "8コア"})
    
a3Button’s setTarget:(me)
    
a3Button’s setAction:("mySelector:")
    
a3Button’s setEnabled:(true)
    
    
    (
aBox’s addSubview:a1Button)
    (
aBox’s addSubview:a2Button)
    (
aBox’s addSubview:a3Button)
    
    
    
–BOX Bをつくる
    
set bBox to (NSBox’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight – 80)))
    (
bBox’s setTitle:("Data"))
    
    
set aScroll to makeTableView(aTList, aWidth, aHeight – 150, labelSortList) of me
    
    (
bBox’s addSubview:aScroll)
    
    
parentView’s setSubviews:{aBox, bBox}
    
    
— set up alert  
    
set theAlert to NSAlert’s alloc()’s init()
    
tell theAlert
      its setMessageText:aMainMes
      
its setInformativeText:aSubMes
      
its addButtonWithTitle:"OK"
      
its addButtonWithTitle:"Cancel"
      
its setAccessoryView:(parentView)
      
      
set myWindow to its |window|
    end tell
    
    
myWindow’s setLevel:(NSModalPanelWindowLevel)
    
    
— show alert in modal loop
    
NSRunningApplication’s currentApplication()’s activateWithOptions:0
    
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
    
if (my returnCode) = 1001 then error number -128
    
    
set tmpResult to (aScroll’s documentView’s selectedRow()) + 1
    
set (my theResult) to contents of item tmpResult of ((my theDataSource) as list)
  end chooseItemByTableView:
  
  
  
on doModal:aParam
    set (my returnCode) to (aParam’s runModal()) as number
  end doModal:
  
  
  
  
  
–TableView Event Handlers
  
on numberOfRowsInTableView:aView
    return (my theDataSource)’s |count|()
  end numberOfRowsInTableView:
  
  
on tableView:aView objectValueForTableColumn:aColumn row:aRow
    set aRec to (my theDataSource)’s objectAtIndex:(aRow as number)
    
set aTitle to (aColumn’s headerCell()’s title()) as string
    
set aRes to (aRec’s valueForKey:aTitle)
    
return aRes
  end tableView:objectValueForTableColumn:row:
  
  
  
  
on makeTableView(aDicList, aWidth, aHeight, labelSortList)
    set aOffset to 40
    
set theDataSource to NSMutableArray’s alloc()’s init()
    
theDataSource’s addObjectsFromArray:aDicList
    
    
set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight))
    
set tView to NSTableView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, aOffset, aWidth, aHeight))
    
    
set aLen to length of labelSortList
    
    
repeat with i in labelSortList
      set j to contents of i
      
set aColumn to (NSTableColumn’s alloc()’s initWithIdentifier:j)
      (
aColumn’s setWidth:(aWidth div aLen))
      (
aColumn’s headerCell()’s setStringValue:j)
      (
tView’s addTableColumn:aColumn)
    end repeat
    
    
tView’s setDelegate:me
    
tView’s setDataSource:me
    
tView’s reloadData()
    
    
aScroll’s setDocumentView:tView
    
tView’s enclosingScrollView()’s setHasVerticalScroller:true
    
aScroll’s setVerticalLineScroll:(30.0 as real)
    
    
–1行目を選択
    
set aIndexSet to NSIndexSet’s indexSetWithIndex:0
    
tView’s selectRowIndexes:aIndexSet byExtendingSelection:false
    
    
–強制的にトップにスクロール
    
set aDBounds to aScroll’s documentView()’s |bounds|()
    
if class of aDBounds = list then
      –macOS 10.13 or later
      
set maxHeight to item 2 of item 1 of aDBounds
    else
      –macOS 10.10….10.12
      
set maxHeight to height of |size| of aDBounds
    end if
    
    
set aPT to current application’s NSMakePoint(0.0, -1 * (maxHeight as real))
    
aScroll’s documentView()’s scrollPoint:aPT
    
    
return aScroll
  end makeTableView
  
  
  
on alertShowHelp:aNotification
    display dialog "Help Me!" buttons {"OK"} default button 1 with icon 1
    
return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする
  end alertShowHelp:
  
  
  
on mySelector:aObject
    set aIndex to (aObject’s indexOfSelectedItem()) as number
    
filterByMultipleCondition() of me
  end mySelector:
  
  
  
  
on filterByMultipleCondition()
    set prediCatesArray to {}
    
    
set aInd to (my a1Button’s indexOfSelectedItem()) as number
    
set bInd to (my a2Button’s indexOfSelectedItem()) as number
    
set cInd to (my a3Button’s indexOfSelectedItem()) as number
    
    
if {aInd, bInd, cInd} = {0, 0, 0} then
      set (my theDataSource) to NSMutableArray’s arrayWithArray:(my aDataList)
      
tView’s reloadData()
      
return
    end if
    
    
–このあたり、複数条件をハードコーディングしているのは超絶頭悪い。項目数の増減に対応できるべき
    
if aInd > 0 then
      set aTitle to (my a1Button’s title()) as string
      
set the end of prediCatesArray to "field1 contains ’" & aTitle & "’"
    end if
    
    
if bInd > 0 then
      set bTitle to (my a2Button’s title()) as string
      
set the end of prediCatesArray to "field2.integerValue < " & bTitle
    end if
    
    
if cInd > 0 then
      set cTitle to (my a3Button’s title()) as string
      
set the end of prediCatesArray to "field3 contains ’" & cTitle & "’"
    end if
    
    
–データ 抽出
    
set tmpList to filterDictArrayByLabel3((my aDataList), prediCatesArray) of me
    
    
–データ 再表示
    
set (my theDataSource) to NSMutableArray’s arrayWithArray:(tmpList)
    
tView’s reloadData()
  end filterByMultipleCondition
  
  
  
  
–リストに入れたレコードを、指定の属性ラベルの値で抽出(複数PredicatesをANDで合成)
  
on filterDictArrayByLabel3(origArray as list, aPredicateList as list)
    set aArray to NSMutableArray’s arrayWithArray:origArray
    
set predArray to NSMutableArray’s new()
    
    
repeat with i in aPredicateList
      (predArray’s addObject:(NSPredicate’s predicateWithFormat:(contents of i)))
    end repeat
    
    
set pred to current application’s NSCompoundPredicate’s andPredicateWithSubpredicates:predArray
    
set filteredArray to aArray’s filteredArrayUsingPredicate:pred
    
    
return filteredArray
  end filterDictArrayByLabel3
end script

★Click Here to Open This Script 

Posted in dialog GUI list Record search | Tagged 10.13savvy 10.14savvy 10.15savvy NSAlert NSAlertSecondButtonReturn NSBox NSColor NSCompoundPredicate NSIndexSet NSModalPanelWindowLevel NSMutableArray NSPopUpButton NSPredicate NSRunningApplication NSScrollView NSTableColumn NSTableView NSView | 1 Comment

CotEditor PowerPackのPiyomaru Software内での位置付け

Posted on 12月 22, 2019 by Takaaki Naganoya

CotEditor向けの機能強化Script群「CotEditor PowerPack」は、自分たちが便利そうだと思った機能をびっしりと敷き詰めて実装してみました(基礎的なScriptingについては、同梱の基礎的なサンプルスクリプト集「BasicPack」にまとめています)。PowerPackを実際に作ってみたら、メニューで項目が増えたときに絵文字によるラベリングが割と有効だという発見ももたらしました。

ただ、PowerPackがPowerPack単体で存在するはずもなく、Piyomaru Softwareが作成している各種プログラムとも密接な関係にあります。歴史的な経緯の中で先行ソフトウェアの影響も受けていますし、さまざまなプロジェクトの成果物や技術の実証の場として利用しているからです。

Tanzakuの部品を利用

具体例を言うと、Tanzaku用に開発した コマンド解析用 簡易日本語形態素解析エンジン「easyJParse」。これはAppleScriptだけで記述した80行ほどの規模の形態素解析プログラムです。これをコマンド解析用以外の、伏せ字処理のプログラムに使っています。

「航空機の部品を炊飯器に転用する」ような違和感はありますが、想定外の用途に部品を使いまわすと意外な発見があります。easyJParseはコマンド解釈用の日本語Parseプログラムであり、長大な文章を解釈するようには実装していません。そこに実際に数十〜数百KBのサイズの日本語テキストを与えてParseするとどうなるかという実験が行えました。実際、ループで文章単位のテキストを与えているため、クラッシュしたり迷走したりすることなく処理できました(それなりに時間はかかりましたが)。データの持ち方をより大規模なデータを与えても大丈夫なように備えていれば、ある程度の大規模データにも備えることができるでしょう。

コマンド構造は日本語音声認識コマンダーの影響

多くのコマンドから全体を構成するノウハウは、2003〜2004年ごろに作っていた日本語音声認識コマンダー(いまのAIスピーカーみたいなもの)「符令韻投句」(ぷれいんとーく)で培ったものです。各コマンドの粒度については小さいほうがいいのか大きいものがあるべきかなどまだ実験中ですが、PowerPackの場合には「細かいコマンドを寄せ集めるとどうなるか」という実験を行なってみています。

Piyomaru Script Assistantに影響

スクリプトエディタの編集エリア上でコンテクストメニューを表示させて呼び出すScript Assistantは、Apple純正のものがOSにデフォルトで入っていますが、網羅性がいまひとつで実用性もさっぱりです。

そこで、Mac OS X 10.3から4の時代にこれを自分に合わせてすべて書き直し、さらに書籍のオマケに出すために網羅性を高めたものが現在配付中のPiyomaru Script Assistantです。

Piyomaru Script AssistantのScriptのうちmacOS 10.13で動かなくなってしまったものがいくつかあり、また、内容についても更新の必要を(さすがに2006年ごろに作ったものなので)感じたため、こちらも強化を行なっています。

さらに、PowerPackで積み重ねた実験結果をPiyomaru Script Assistantにフィードバック。CotEditorのPowerPackで培ったメニューにおける絵文字の活用ノウハウが生かされており、また、初心者に違和感なくCocoa Scriptingの部品を使ってもらえるような配慮を行っています(Cocoaの機能をまったく使わないVanilla Scriptの中にCocoa ScriptingのScriptingモジュールを埋め込む格好)。

そもそも、本Blogがスタートした経緯そのものが、すべてAppleScriptで記述した人工知能インタフェース「Newt On」(文字版のSiri)の内部ルーチン(部品)のメンテナンスとか共有が目的だったので、Piyomaru SoftwareのプログラムはおしなべてNewt Onの影響を受けていたり、そのものの部品を使っていたりもします。

これらの技術や経験もすべてTanzakuに向けて蓄積されているところです。

Posted in PRODUCTS | Tagged 10.14savvy 10.15savvy | Leave a comment

アラビア語ローカライズしたアプリケーションの挙動の変化

Posted on 12月 22, 2019 by Takaaki Naganoya

Xcode上でAppleScriptのアプリケーションを作って(Double PDF)、各国語にローカライズしていたときに、最難関言語として名高いアラビア語(Arabic)を試してみたことがありました。

ローカライズ作業自体にもAppleScriptを投入し、テキストエディタ上でオープンしているstringsファイルを読み取ってGoogle Translate APIを呼び出して指定言語に数秒で翻訳。記号類だけから構成されるフィールドは翻訳しないなど、その場でScriptを調整しながら大幅な翻訳作業の省力化を実現(ほかの方法もあるようなので、これがベストとは言いませんが、、、)。このScriptなしに他の言語への翻訳などというめんどくさい作業はやろうとは思いませんでした。

この翻訳用AppleScriptの威力で30言語ぐらい翻訳。主要言語のうち、最後に残ったのが、文字が右から左に流れるアラビア語とヘブライ語でした。

まずは、挙動がどのぐらい違うのか確認。Xcodeでローカライズ言語にアラビア語を追加。stringファイルの内容自体はオリジナルの英語のままの状態で、実行時のアプリケーションの言語環境に「アラビア語」を指定して起動してみました。

起動してびっくり!


▲左:日本語環境、右:アラビア語環境


▲日本語環境を指定して起動したところ@macOS 10.14.6


▲アラビア語環境を指定して起動したところ@macOS 10.14.6


▲アラビア語環境で表示したメニュー@macOS 10.14.6


▲アラビア語環境で表示したAbout Box@macOS 10.14.6。スクロールバーが右側ではなく左側に

ツールバーアイコンはデフォルトの英語環境や日本語環境では、左→右の順で並びますが、アラビア語環境ではウィンドウ上部右→左と並びました。メニューの内容も右側にタイトルが来て、左側にキーボードショートカットが並ぶなど、予想外の配置です。

これは、バグとかいった種類の話ではなく、はじめてアラビア語環境で自作のアプリケーションを起動して、その挙動の違いに驚かされたという話であります。

2つのPDFViewを並べてあり、それぞれ右とか左とか言わなくてもわかるよう、左側には青色のラベル、右側には赤色のラベルを貼っておいたのですが、ツールバーアイコンの左右も入れ替わってしまい、自分の意図したとおりのレイアウトからはかけ離れたものとなってしまいました。

アプリケーション内部で、アプリケーション起動環境から言語がアラビア語やヘブライ語のように右→左の表示を行う言語だった場合には何か処理を行なってツールバーボタンの入れ替えなどを行う必要があることでしょうか。ちょっとノーアイデアで分からないところ。ひたすら驚かされました。他の言語は軒並みGoogle Translation APIをAppleScriptから呼び出して翻訳できたのですが、アラビア語とヘブライ語は難敵でした。攻略できていないので、そこんとこなかなか辛いです。

Double PDF v2.0自体はMac App Storeで絶賛レビュー中です。In Reviewの状態に入ってからはや10日が経過し、さすがに不安になってDeveloper Connectionに電話して聞いてしまいましたが、わかったのは本当にまだレビュー作業中で、レビューにさらなる時間がかかるということだけです。

そろそろ、実際にアップデート作業にかけた時間よりもレビューにかかっている時間のほうが長くなりつつあり、そして確実に数倍の時間がかかりそうでもあり……各国語のPDFでも作って(表示をローカライズした30言語分)、それらのPDFで差分検出チェックでもしてるんじゃないかと、、、

Posted in AppleScript Application on Xcode | Tagged 10.14savvy | Leave a comment

PermissionsKitでユーザー権限のチェックとリクエスト(フルディスクアクセス)

Posted on 12月 19, 2019 by Takaaki Naganoya

PermissionsKit.frameworkの機能を呼び出して、実行中のアプリケーションがフルディスクアクセスの権限を持っているかどうか確認を行い、持っていなかった場合には権限を許可してもらえることを願ってシステム環境設定の「セキュリティとプライバシー」>「セキュリティ」を表示します。

–> Download PermissionsKit_tester(Code-Signed Executable Applet with Framework in its bundle)

だいたいはサンプルのObjective-CのプログラムをAppleScriptに翻訳して実行しているだけですが、1箇所だけ発見がありました。

ご存知のとおりBlocks構文はAppleScriptでは書けないので、Blocks構文の記述が要求されるAPIはAppleScriptから呼び出せません。

本FrameworkのAPIも権限を要求するときにBlocks構文の記述が求められるのですが、ためしにBlocks(^)の記述を要求される箇所にヌルを指定してみたところ、、、、動きました(^ー^;;;;;;

# なんでも効くわけではないようです

あー、Blocks構文のところにヌルを指定すると動くんだー。処理終了時に実行する内容をBlocksの中に書くのを、何も書かないことで同期実行とほぼ同じ扱いができるんじゃないかと。いろいろ試してみると発見があるかもしれません。

# 今日、Edama2さんと世間話していたら「パラメータとしてBlocks構文を必要とされる箇所にmissing valueを入れて動いたケースもあったよ」とのこと。そういうの重要なので教えてほしかったー(T_T)

PermissionsKit.frameworkでは各種権限設定の確認と要求が行えるようにはなっているのですが、フルディスクアクセス以外はすべてクラッシュして動かなかったので、フルディスクアクセスの権限確認&要求専用とみなしています。

AppleScript名:PermissionsKitでユーザー権限のチェックとリクエスト(フルディスクアクセス).scptd
—
–  Created by: Takaaki Naganoya
–  Created on: 2019/12/19
—
–  Copyright © 2019 Piyomaru Software, All Rights Reserved
—
use AppleScript version "2.4" — Yosemite (10.10) or later
use framework "Foundation"
use framework "PermissionsKit" –https://github.com/MacPaw/PermissionsKit
use scripting additions

property MPPermissionTypeCalendar : 0
property MPPermissionTypeReminders : 1
property MPPermissionTypeContacts : 2
property MPPermissionTypePhotos : 3
property MPPermissionTypeFullDiskAccess : 4

–MPPermissionTypeFullDiskAccess 以外はクラッシュして処理継続できなかった

set aPerm to current application’s MPPermissionsKit’s alloc()’s init()
set pRes to current application’s MPPermissionsKit’s authorizationStatusForPermissionType:(MPPermissionTypeFullDiskAccess)

set sRes to getStatus(pRes) of me
log sRes

if pRes is not equal to 0 then
  set pRes to current application’s MPPermissionsKit’s requestAuthorizationForPermissionType:(MPPermissionTypeFullDiskAccess) withCompletion:""
end if

on getStatus(aFlag)
  if aFlag = 0 then
    return "Denied" –拒否された
  else if aFlag = 1 then
    return "Authorized" –承認ずみ
  else if aFlag = 2 then
    return "Not determined" –未定
  end if
end getStatus

★Click Here to Open This Script 

Posted in Security | Tagged 10.13savvy 10.14savvy 10.15savvy | Leave a comment

画像の空白判定 v4

Posted on 12月 19, 2019 by Takaaki Naganoya

画像のすべてのピクセルが白であることをチェックするAppleScriptです。

以前にmacOS 10.12上で作成した「空白画像検出v3」は一般的に処理時間のかかる空白画像の検出(ヒストグラム計算してチェックする?)が高速に処理できます(GPUImageでヒストグラム計算を行うより2倍ぐらい高速)。空白検出のためだけにAdobe Photoshopが必要になるといった事態は避けられます。

–> test Data(動作検証用各種テストデータ)

macOS 10.14.6上でこのルーチンを再度試してみたところ、思ったとおりに空白検出(数百万ピクセルの画像でも1つだけ黒であればfalseを返す)してくれません。ちょっと書き方を変えていますが、単体で通常のAppleScript(Cocoa不使用)にコンテクストメニューから突っ込むモジュールとして運用するためです。

copyコマンドがdeep copyしてくれない?

参照ではなくすべてのデータをコピーするコマンドとして、copyコマンドはとても重宝しています。単に「パラメータの代入の方向が違う偏屈なコマンド」ではなく、明示的にデータ内容をコピーするためのコマンドと認識しています。

AppleScriptのオブジェクト同様、Cocoaのオブジェクトについてもcopyコマンドでdeep copyしてくれるものと理解していましたが、macOS 10.14.6上で本ルーチンを試してみたところ、どうも参照をコピーしている気配がします。

AppleScriptのオブジェクト(配列とか)をcopyコマンドでコピーすると、参照ではなくデータが複製されていることを確認しました。Cocoaオブジェクトのcopyも同様かどうかは、ちょっとそうじゃないんじゃないかというところです。

set bNSImage to aNSImage's |copy|()

Cocoaの世界のオブジェクトのコピーはこんな感じ(↑)でできたので、今後はこちらを採用することにします。

1×1のNSImageに色を塗るとデータサイズが増える

ビットマップ画像の状態であるNSBitmapImageRepになっていれば、1×1画像のサイズは同じことが期待されます。実際、macOS 10.12上ではそのように扱えていました。

ところが、macOS 10.14上で1×1ドットのNSImageに対して色を塗って、NSBitmapImageRepを取得すると、塗らない状態のNSImageよりもデータ(NSData)サイズが大きくなることがわかりました。


▲1×1のPNG画像をビットマップ化したデータ。赤が処理前、青が塗りつぶし処理後のデータ(macOS 10.14.6)。ピクセル数が増えてるのでは? と疑ってサイズを何回も計算して確認しましたが、間違っていません

しかも、データ量がmacOS 10.14と10.15では大幅に異なります(macOS 10.15では大幅にデータ量が減る)。

 1×1 PNG画像 ビットマップ化したデータサイズ:3,354 Bytes(macOS 10.14.6)
 1×1 PNG画像 塗りつぶし ビットマップ化したデータサイズ:3,574 Bytes(macOS 10.14.6)
 1×1 PNG画像 塗りつぶし ビットマップ化したデータサイズ:750 Bytes(macOS 10.15.2)

さすがに匙を投げかけましたが、比較元のデータに透明の色(clearColor())を塗る=画像的に意味はないが、同じ処理を通すことでデータサイズを同程度にするという処理を行うことで、いい感じに空白検出できるようになりました。

なにをどういじくったら、1×1ビットマップ画像のサイズがOSアップデートごとに大幅に変わるのかさっぱり理解できないのですが、そこに何か意味があるのでしょうか?

Mac App Storeに出したアプリケーションで、PDFの空白ページ検出に本ルーチンを利用していますが、Appleのレビュー段階で「単にPDFから文字を抽出して空白検出しているのだろう」と思われてリジェクトされました。実際には、全ページを画像レンダリングして1ドットの画像でも存在していたら空白としては認識しない仕様になっているのですが、Appleのレビューワーには処理内容を説明して、各種ベンチマーク結果などを出さないと信じてもらえませんでした。

Appleのエンジニアが考えるところの空白検出が「文字チェックだけ」の使い物にならない処理だということはよくわかりました。また、頭からそのように思い込んで攻撃してきた間抜けにも遭遇してウンザリしました。

AppleScript名:画像の空白判定 v4
set aFile to (choose file of type {"public.image"})
set iRes to checkImageIsWhite(aFile) of whiteImageKit
–> true –white (blank) image

script whiteImageKit
  use AppleScript version "2.7" — High Sierra (10.13) or later
  
use framework "Foundation"
  
use framework "AppKit"
  
use scripting additions
  
property parent : AppleScript
  
  
property NSData : a reference to current application’s NSData
  
property NSDate : a reference to current application’s NSDate
  
property |NSURL| : a reference to current application’s |NSURL|
  
property NSColor : a reference to current application’s NSColor
  
property NSImage : a reference to current application’s NSImage
  
property NSBezierPath : a reference to current application’s NSBezierPath
  
property NSBitmapImageRep : a reference to current application’s NSBitmapImageRep
  
  
–Compare Original Data and
  
on checkImageIsWhite(aFile)
    set aPOSIXpath to POSIX path of aFile
    
set aURL to |NSURL|’s fileURLWithPath:(aPOSIXpath)
    
    
set aNSImage to NSImage’s alloc()’s initWithContentsOfURL:(aURL)
    
set bNSImage to NSImage’s alloc()’s initWithContentsOfURL:(aURL)
    
    
–copy aNSImage to bNSImage–Not deep copy ????
    
    
set fillColor1 to NSColor’s clearColor()
    
set blankNSImage1 to drawImageWithFilledColor(aNSImage, fillColor1) of me
    
    
set fillColor2 to makeNSColorFromRGBAval(65535, 65535, 65535, 65535, 65535) of me
    
set blankNSImage2 to drawImageWithFilledColor(bNSImage, fillColor2) of me
    
    
set aTiff to blankNSImage1’s TIFFRepresentation()
    
set bTiff to blankNSImage2’s TIFFRepresentation()
    
    
set chkWhite to (aTiff’s isEqualToData:bTiff) as boolean
    
    
return chkWhite
  end checkImageIsWhite
  
  
  
on getSizeOfImage(anNSImage)
    set aSize to anNSImage’s |size|()
    
set aClass to class of aSize
    
if aClass = record then
      copy aSize to theSize –To macOS 10.12.x
    else –macOS 10.13 or later
      set sizeX to (item 1 of item 2 of aSize)
      
set sizeY to (item 2 of item 2 of aSize)
      
set theSize to {width:sizeX, height:sizeY}
    end if
    
return theSize
  end getSizeOfImage
  
  
  
–指定サイズの画像を作成し、背景を指定色で塗る
  
on drawImageWithFilledColor(anImage, fillColor)
    set aSize to getSizeOfImage(anImage) of me
    
    
anImage’s lockFocus()
    
    
set theRect to {{x:0, y:0}, {width:(width of aSize), height:(height of aSize)}}
    
set theNSBezierPath to NSBezierPath’s bezierPath
    
theNSBezierPath’s appendBezierPathWithRect:theRect
    
fillColor’s |set|()
    
theNSBezierPath’s fill()
    
    
anImage’s unlockFocus()
    
    
return anImage
  end drawImageWithFilledColor
  
  
  
–aMaxValを最大値とする数値でNSColorを作成して返す
  
on makeNSColorFromRGBAval(redValue as integer, greenValue as integer, blueValue as integer, alphaValue as integer, aMaxVal as integer)
    set aRedCocoa to (redValue / aMaxVal) as real
    
set aGreenCocoa to (greenValue / aMaxVal) as real
    
set aBlueCocoa to (blueValue / aMaxVal) as real
    
set aAlphaCocoa to (alphaValue / aMaxVal) as real
    
set aColor to NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa
    
return aColor
  end makeNSColorFromRGBAval
  
end script

★Click Here to Open This Script 

Posted in Image | Tagged 10.13savvy 10.14savvy 10.15savvy NSBezierPath NSBitmapImageRep NSColor NSData NSImage NSURL | 3 Comments

元号変換v41

Posted on 12月 19, 2019 by Takaaki Naganoya

西暦→元号の変換を行うAppleScriptです。誰もがこんな感じのプログラムを作って(書き捨てて)いると思うのですが、不思議と誰も公開しないという、、、

Japanese Gengo is only for Japanese calendar. It is old-style age names in Japanese. I don’t care of it for daily use.

AppleScript名:元号変換v41
set a to "2019/7/21"
set {aGengoStr, aGengoNum} to retJapaneseGengo(a) of JGengoKit
–> {"令和", 1}

script JGengoKit
  on retJapaneseGengo(aDate as string)
    set aDateObj to date aDate
    
    
tell current application
      set aYear to year of aDateObj
      
set aMonth to month of aDateObj as number
      
set aDay to day of aDateObj
      
      
set aStr to retZeroPaddingText(aYear, 4) of me & retZeroPaddingText(aMonth, 2) of me & retZeroPaddingText(aDay, 2) of me
      
      
set aGengo to ""
      
if aStr ≥ "20190501" then
        set aGengo to "令和"
        
set aGengoNum to aYear – 2019 + 1
      else if aStr ≥ "19890108" then
        set aGengo to "平成"
        
set aGengoNum to aYear – 1989 + 1
      else if aStr ≥ "19261225" then
        set aGengo to "昭和"
        
set aGengoNum to aYear – 1926 + 1
      else if aStr ≥ "19120730" then
        set aGengo to "大正"
        
set aGengoNum to aYear – 1912 + 1
      else if aStr ≥ "18680125" then
        set aGengo to "明治"
        
set aGengoNum to aYear – 1868 + 1
      end if
      
      
return {aGengo, aGengoNum}
    end tell
  end retJapaneseGengo
  
  
–数値にゼロパディングしたテキストを返す
  
on retZeroPaddingText(aNum, aLen)
    set tText to ("0000000000" & aNum as text)
    
set tCount to length of tText
    
set resText to text (tCount – aLen + 1) thru tCount of tText
    
return resText
  end retZeroPaddingText
end script

★Click Here to Open This Script 

Posted in Calendar | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | 2 Comments

macOS 10.13以降、スクリプトエディタのヘルプが更新され続けて驚く

Posted on 12月 18, 2019 by Takaaki Naganoya

力が入っているのか抜けているのかわかりませんが、スクリプトエディタのヘルプがOSのメジャーバージョンアップごとに更新されているのを見つけて驚かされました。

 「スクリプトエディタヘルプ」(macOS High Sierra用)
 「スクリプトエディタユーザーガイド macOS Mojave用」
 「スクリプトエディタユーザーガイド macOS Catalina用」

などと、わざわざOSごとに更新され、日本語環境用に翻訳されています。ちょっと驚きました。

ただ、相変わらず内容は「は?」とか「えーー?」とかいう感想しか出てこないものなので、存在している以上の実質的な価値はありません。存在しないよりは数万倍よいのですが、「これを読んで使えるようにはならないだろー」という程度のものです。


▲macOS 10.13用スクリプトエディタユーザガイド。このScreen ShotのScriptは実際に動くので好感が持てるのですが、なぜかこれが次のOSから変更されています。単に「代わり映えしないから変更した」ぐらいの意図であればよいのですが、、、


▲macOS 10.14用スクリプトエディタユーザガイド


▲macOS 10.15用スクリプトエディタユーザガイド

冒頭から内容が、

「OS X 10.10 以降では、AppleScript に加え、スクリプト言語である JavaScript for Automation を使用してスクリプトを記述することができます。また、シェルスクリプトや、UserTalk などの他社製のスクリプト言語を使用してスクリプトを記述することもできます。」

とあり、「あたかもシェルスクリプトをOSA言語的に扱えるかのような間違った印象を与えてしまう」「UserTalk(Frontier)なんてもう誰も使っていないし、消滅して久しいぞ」といったツッコミを行なってしまうところですが、Apple社内の現場が内容のチェックをしないで秘伝のタレのように注ぎ足し注ぎ足しで更新しているだけだと痛感させられます。

内容は機械的に翻訳しているだけのようで、コンテクストメニューから呼び出せるApple純正のScriptはみんなローカライズされていない(事実)のに、ヘルプ内では名称などが日本語訳されて紹介されており、実際にコンテクストメニューを表示させると困惑させられること請け合いです。外注の翻訳会社のせいではなく、Apple側が何も指定しなかったので機械的に翻訳しただけでしょう。


▲macOS 10.15上のスクリプトエディタヘルプでは、コンテクストメニューの項目名が勝手に日本語訳されている。実物は英語なのに、、、、


▲実際にmacOS 10.15上のスクリプトエディタでコンテクストメニューを表示すると英語のまま

macOS標準搭載のコンテクストメニューScriptがあまりにも使えないので、全部捨てて入れ替えて使えるものを突っ込んだものが「Piyomaru Script Assistant」なわけですが、電子書籍のオマケとして付けたこのScriptもmacOS 10.13でいろいろ動かないものが出てきており、ちょうど機会があったので10.14/10.15用にアップデートしました(10.13対応はちょっとダメだと思います。バグの問題というよりも、絵文字の互換性がないので)。

CotEditor用のPowerPackの影響を受けて、そういう方向のScriptも突っ込んでいます。スクリプトエディタのコンテクストメニューから呼び出したAppleScriptから、スクリプトエディタのウィンドウをぐるぐる回してみようとしたら、ほとんど再描画されずに結果だけ表示されるという一幕もありました。

Posted in Bug | Tagged 10.13savvy 10.14savvy 10.15savvy Script Editor | Leave a comment

macOS 10.14でScript Editorのsdefから「execute」コマンドが除去されていた

Posted on 12月 16, 2019 by Takaaki Naganoya

macOS 10.14のスクリプトエディタのAppleScript用語辞書(sdef)から「execute」コマンドが除去されていることに気づきました。

このことは、別に「GUI側からスクリプトエディタ上のAppleScriptを実行できなくなった」ということではありません。

スクリプトエディタ自体もAppleScriptからコントロールできる「スクリプタブルな」アプリケーションであり、macOS 10.14以降ではAppleScriptからスクリプトエディタをコントロールしてAppleScriptを実行させることができなくなった、ということです。

セキュリティ向上のためにexecuteコマンドを削除したように見えますが、そういうことをやったならRelease Notesに明記しておいてほしいものです。

Piyomaru Context menu AssistantのmacOS 10.13版を10.14上で動作確認していたら、動かなくなっているものがあって(クラッシュするものも出てきております)、原因を確認していたら一部の予約語が、

with timeout of 36000 seconds --1時間のタイムアウト
	«event sedsexec»
end timeout

のように文字化け。これによって「execute」(Script実行)の予約語が抹消されたことがわかりました。スクリプトエディタ自体をコントロールしてScriptを実行させるケースは少ないので、世界中でも私ぐらいしか影響はないことでしょう。ちなみに、サードパーティのAppleScript統合開発環境であるScript Debuggerにはexecuteコマンドがあります。

別にスクリプトエディタでAppleScript書類をオープンして実行するような迂遠かつマニアックかつ「もっと簡単な手段があるのにわざわざそんなことしなくても」というアクションを好き好んで行う人はほとんどいないでしょう。全人類のうち、私以外にダメージはないことでしょう。

実際にスクリプトエディタにexecuteコマンドを送って実行していた例というのは、実行時間の計測を行うAppleScriptです。地味にそういうのを使っていました(最近は、Shane StanleyのScript Geekで処理時間を計測するパターンが多いので使っていませんでしたが)。


▲macOS 10.13.6


▲macOS 10.13.6


▲macOS 10.14.6


▲macOS 10.14.6


▲macOS 10.15.2


▲macOS 10.15.2

Posted in sdef | Tagged 10.14savvy 10.15savvy Script Editor | Leave a comment

choose multiple path Script Libraryをv2.1にアップデート

Posted on 12月 16, 2019 by Takaaki Naganoya

NSPathControlでドラッグ&ドロップにより複数のパス情報を設定するダイアログUIを提供するAppleScriptライブラリ「choose multiple path Script Library」をv2.1にアップデートしました。

–> Download choosePathLib.scptd(~/Library/Script Libraries)

変更点:
・dialog widthでダイアログの表示幅を指定できるようにした

・NSPathControlの配色がDarkModeに合わなかったので、色は無指定にした

・AppleScript用語辞書にサンプルAppleScript(URLリンク入り)と実行結果イメージを入れた(分かりやすさ、使い勝手Up)

さまざまなGUI部品を使ってアラートダイアログ上に箱庭ユーザーインタフェースを作り込んだ場合に、通常のAppleScript書類のままだと、ランタイム環境(とくにScript Debugger)の差異の影響を受けてドラッグ&ドロップを受信できないとか実行時に明示的にメインスレッド実行が必要になるケースが見られます。

AppleScript用語辞書を通じてアクセスすることで、そうした問題を「うやむやにできる」ことがわかってきたので(技術的には説明できないものの、だいたいそんなもんだろうと予想はしていました)、こうした再利用の可能性が高いGUI利用部品は積極的にライブラリにまとめています。

Posted in Script Libraries | Tagged 10.12savvy 10.13savvy 10.14savvy 10.15savvy | Leave a comment

Post navigation

  • Older posts
  • Newer posts

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • 開発機としてM2 Mac miniが来たのでガチレビュー
  • macOS 15, Sequoia
  • Pages本執筆中に、2つの書類モード切り替えに気がついた
  • Numbersで選択範囲のセルの前後の空白を削除
  • メキシカンハットの描画
  • Pixelmator Pro v3.6.4でAppleScriptからの操作時の挙動に違和感が
  • AppleScriptによる並列処理
  • macOS 15でも変化したText to Speech環境
  • Safariで「プロファイル」機能を使うとAppleScriptの処理に影響
  • デフォルトインストールされたフォント名を取得するAppleScript
  • AppleScript入門③AppleScriptを使った「自動化」とは?
  • 【続報】macOS 15.5で特定ファイル名パターンのfileをaliasにcastすると100%クラッシュするバグ
  • macOS 15 リモートApple Eventsにバグ?
  • Script Debuggerの開発と販売が2025年に終了
  • AppleScript入門① AppleScriptってなんだろう?
  • macOS 14で変更になったOSバージョン取得APIの返り値
  • NSObjectのクラス名を取得 v2.1
  • macOS 15:スクリプトエディタのAppleScript用語辞書を確認できない
  • 有害ではなくなっていたSpaces
  • AVSpeechSynthesizerで読み上げテスト

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1391) 10.14savvy (587) 10.15savvy (438) 11.0savvy (283) 12.0savvy (212) 13.0savvy (198) 14.0savvy (151) 15.0savvy (140) CotEditor (66) Finder (51) Keynote (119) NSAlert (61) NSArray (51) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (53) NSDictionary (28) NSFileManager (23) NSFont (21) NSImage (41) NSJSONSerialization (21) NSMutableArray (63) NSMutableDictionary (22) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (119) NSURL (98) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (76) Pages (55) Pixelmator Pro (20) Safari (44) Script Editor (27) WKUserContentController (21) WKUserScript (20) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • Beginner
  • Benchmark
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • check sum
  • Clipboard
  • Cocoa-AppleScript Applet
  • Code Sign
  • Color
  • Custom Class
  • date
  • dialog
  • diff
  • drive
  • Droplet
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Localize
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • parallel processing
  • PDF
  • Peripheral
  • process
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2025年7月
  • 2025年6月
  • 2025年5月
  • 2025年4月
  • 2025年3月
  • 2025年2月
  • 2025年1月
  • 2024年12月
  • 2024年11月
  • 2024年10月
  • 2024年9月
  • 2024年8月
  • 2024年7月
  • 2024年6月
  • 2024年5月
  • 2024年4月
  • 2024年3月
  • 2024年2月
  • 2024年1月
  • 2023年12月
  • 2023年11月
  • 2023年10月
  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC