Archive for the 'NSTextView' Category

2015/11/26 動的にテキストビューを表示

動的にNSTextViewを作成してログ表示するAppleScriptです。

textview1.png

Script Editor上でControl+Command+Rで、ASObjC Explorer 4上では「Run in Foreground」をチェックして実行する必要があります。

AppleScript名:ASOCでテキストビューを表示
– Created 2015-11-25 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set aWidth to 400
set aHeight to 600
set aColor to current application’s NSColor’s colorWithDeviceRed:0.0 green:0.0 blue:0.0 alpha:1.0
set aTitle to “テキストビューのじっけん/TextView Test”
set outText to “ぴよまるソフトウェア / Piyomaru Software “

set aScroll to current application’s NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))
set aView to current application’s NSTextView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aWidth, aHeight))

set aStr to current application’s NSMutableString’s alloc()’s init()

aView’s setRichText:true
aView’s useAllLigatures:true
aView’s setTextColor:(current application’s NSColor’s cyanColor())

aView’s setBackgroundColor:aColor
aScroll’s setDocumentView:aView
aView’s enclosingScrollView()’s setHasVerticalScroller:true

set aWin to makeWinWithView(aScroll, aWidth, aHeight, aTitle, 0.8)
aWin’s makeKeyAndOrderFront:(missing value)
aWin’s makeFirstResponder:aView

repeat with i from 1 to 100
  set bStr to (current application’s NSMutableString’s stringWithString:(outText & (i as string) & return))
  
set aStr to (bStr’s stringByAppendingString:aStr)
  (
aView’s setString:aStr)
end repeat

my closeWin:aWin

–make Window for Input
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle, alphaV)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
set aBacking to current application’s NSTitledWindowMask –NSBorderlessWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
– Window
  
set aWin to current application’s NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen)
  
aWin’s setBackgroundColor:(current application’s NSColor’s whiteColor())
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:false
  
aWin’s setLevel:(current application’s NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setAlphaValue:alphaV –append
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s makeKeyAndOrderFront:(me)
  
  
– Set Custom View
  
aWin’s setContentView:aView
  
  
return aWin
  
end makeWinWithView

–close win
on closeWin:aWindow
  delay 5
  
repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

★Click Here to Open This Script 

2015/09/22 クリップボードの内容をRTFとPDFとHTMLで書き出す

Cocoaの機能を用いて、クリップボードの内容をデスクトップにRTFとPDFで書き出すAppleScriptの改訂版です。

前バージョンのAppleScriptでは、スタイル付きテキスト(NSAttributedString)をHTMLに書き出すと、HTML内のタグでは「UTF-8」になっていながらも、HTMLのテキスト自体のエンコーディングがShift JISというたいへん不思議な状態になっていました。

スタイル付きテキスト(NSAttributedString)の取得部分に問題がないことを確認。スタイル付きテキストをPDFやRTFに書き出した場合には問題なし。HTMLの書き出しに固有の根の深い問題があるのかと疑っていましたが・・・難易度でいえば、それほど難しくない話でした。

修正部分はたった1箇所。最後にHTMLをファイルに書き込む際に、UTF-8(NSUTF8StringEncoding)を指定する記述を追加しただけです。

テキストエンコーディングの省略時にはかならず「UTF-8」が指定されるものとばかり思っていましたが、明示的に指定しないとダメということがよくわかりました。

AppleScript名:クリップボードの内容をRTFとPDFとHTMLで書き出す v2
– Created 2015-09-20 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit” – for NSPasteboard, which is the clipboard

–クリップボードの内容をNSAttributedStringに
set anAttr to my getClipboardASStyledText()

–保存先とファイル名を求める
set targFol to POSIX path of (path to desktop)
set aUUID to current application’s NSUUID’s UUID()’s UUIDString() as text

set aRes to my saveStyledTextAsRTF(aUUID, targFol, anAttr) –RTFで書き出す
set bRes to my saveStyledTextAsPDF(aUUID, targFol, anAttr) –PDFで書き出す
set cRes to my saveStyledTextAsHTML(aUUID, targFol, anAttr) –HTMLで書き出す

– クリップボードの内容をNSAttributedStringとして取り出して返す
on getClipboardASStyledText()
  set theNSPasteboard to current application’s NSPasteboard’s generalPasteboard()
  
set theAttributedStringNSArray to theNSPasteboard’s readObjectsForClasses:({current application’s NSAttributedString}) options:(missing value)
  
set theNSAttributedString to theAttributedStringNSArray’s objectAtIndex:0
  
return theNSAttributedString
end getClipboardASStyledText

–スタイル付きテキストを指定フォルダ(POSIX path)にRTFで書き出し
on saveStyledTextAsRTF(aFileName, targFol, aStyledString)
  –Convert NSMutableStyledStrings to RTF
  
set bstyledLength to aStyledString’s |string|()’s |length|()
  
set bDict to current application’s NSDictionary’s dictionaryWithObject:“NSRTFTextDocumentType” forKey:(current application’s NSDocumentTypeDocumentAttribute)
  
set bRTF to aStyledString’s RTFFromRange:(current application’s NSMakeRange(0, bstyledLength)) documentAttributes:bDict
  
  
– build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“rtf”
  
  
return (bRTF’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsRTF

–スタイル付きテキストを指定フォルダ(POSIX path)にPDFで書き出し
on saveStyledTextAsPDF(aFileName, targFol, aStyledString)
  – get page size being used for printing
  
set printInfo to current application’s NSPrintInfo’s sharedPrintInfo()
  
set pageSize to printInfo’s paperSize()
  
set theLeft to printInfo’s leftMargin()
  
set theTop to printInfo’s topMargin()
  
  
– make a text view
  
set theView to current application’s NSTextView’s alloc()’s initWithFrame:{origin:{x:0, y:0}, |size|:pageSize}
  
theView’s setTextContainerInset:{theLeft, theTop}
  
  
– put in the text
  
theView’s textStorage()’s setAttributedString:aStyledString
  
set theData to theView’s dataWithPDFInsideRect:{origin:{x:0, y:0}, |size|:pageSize}
  
  
– build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“pdf”
  
  
return (theData’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsPDF

–スタイル付きテキストを指定フォルダ(POSIX path)にHTMLで書き出し
on saveStyledTextAsHTML(aFileName, targFol, aStyledString)
  –Convert NSMutableStyledStrings toHTML
  
set theNSDictionary to current application’s NSMutableDictionary’s dictionaryWithObject:(current application’s NSHTMLTextDocumentType) forKey:(current application’s NSDocumentTypeDocumentAttribute)
  
set theNSData to aStyledString’s dataFromRange:{location:0, |length|:aStyledString’s |length|()} documentAttributes:theNSDictionary |error|:(missing value)
  
set aHTML to current application’s NSString’s alloc()’s initWithData:theNSData encoding:(current application’s NSUTF8StringEncoding)
  
  
– build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“html”
  
  
return (aHTML’s writeToFile:thePath atomically:true encoding:(current application’s NSUTF8StringEncoding) |error|:(missing value)) as boolean
  
end saveStyledTextAsHTML

★Click Here to Open This Script 

2015/09/20 クリップボードの内容をRTFとPDFで書き出す

Cocoaの機能を用いて、クリップボードの内容をデスクトップにRTFとPDFで書き出すAppleScriptです。

HTMLでも書き出せるのですが、日本語の文字化け(UTF-8で書き出したつもりがShift JISになっていた問題)が解決されていないため、とりあえずこんなもんで。

AppleScript名:クリップボードの内容をRTFとPDFで書き出す
– Created 2015-09-20 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit” – for NSPasteboard, which is the clipboard

–クリップボードの内容をNSAttributedStringに
set anAttr to my getClipboardASStyledText()

–保存先とファイル名を求める
set targFol to POSIX path of (path to desktop)
set aUUID to current application’s NSUUID’s UUID()’s UUIDString() as text

set aRes to my saveStyledTextAsRTF(aUUID, targFol, anAttr) –RTFで書き出す
set bRes to my saveStyledTextAsPDF(aUUID, targFol, anAttr) –PDFで書き出す

– クリップボードの内容をNSAttributedStringとして取り出して返す
on getClipboardASStyledText()
  set theNSPasteboard to current application’s NSPasteboard’s generalPasteboard()
  
set theAttributedStringNSArray to theNSPasteboard’s readObjectsForClasses:({current application’s NSAttributedString}) options:(missing value)
  
set theNSAttributedString to theAttributedStringNSArray’s objectAtIndex:0
  
return theNSAttributedString
end getClipboardASStyledText

–スタイル付きテキストを指定フォルダ(POSIX path)にRTFで書き出し
on saveStyledTextAsRTF(aFileName, targFol, aStyledString)
  –Convert NSMutableStyledStrings to RTF
  
set bstyledLength to aStyledString’s |string|()’s |length|()
  
set bDict to current application’s NSDictionary’s dictionaryWithObject:“NSRTFTextDocumentType” forKey:(current application’s NSDocumentTypeDocumentAttribute)
  
set bRTF to aStyledString’s RTFFromRange:(current application’s NSMakeRange(0, bstyledLength)) documentAttributes:bDict
  
  – build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“rtf”
  
  return (bRTF’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsRTF

–スタイル付きテキストを指定フォルダ(POSIX path)にPDFで書き出し
on saveStyledTextAsPDF(aFileName, targFol, aStyledString)
  – get page size being used for printing
  
set printInfo to current application’s NSPrintInfo’s sharedPrintInfo()
  
set pageSize to printInfo’s paperSize()
  
set theLeft to printInfo’s leftMargin()
  
set theTop to printInfo’s topMargin()
  
  – make a text view
  
set theView to current application’s NSTextView’s alloc()’s initWithFrame:{origin:{x:0, y:0}, |size|:pageSize}
  
theView’s setTextContainerInset:{theLeft, theTop}
  
  – put in the text
  
theView’s textStorage()’s setAttributedString:aStyledString
  
set theData to theView’s dataWithPDFInsideRect:{origin:{x:0, y:0}, |size|:pageSize}
  
  – build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“pdf”
  
  return (theData’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsPDF

★Click Here to Open This Script 

2015/09/18 Notes上の指定のエントリをPDFやRTFとして書き出す

Cocoaの機能を使って、Notes(日本語名:「メモ」)の指定エントリの内容をPDFやRTFとして書き出すAppleScriptです。

  「・・・そんなもん作ってどうするんだ、本当に必要なのか?」

と、私自身が感じた内容ではありましたが、Shaneが質問に答えてMLに投稿し、それを私が日本語環境で検証して「文字化けするよー」とメールで報告してやりとりして、「ああ、Encodingがちがうんだー」ということでめでたく動くようになりました(NotesがデータをUTF-8ではなくUTF-16で保持していたのが原因ですが・・・El Capitanの新形式=iOS9上の新形式 だとどーなんだろう???)。

動くようになってはみたものの、あまりに特定の目的に最適化されたScriptだったので、データ取得部分と保存部分を別々に分け、スタイル付きテキストをPDFやRTFとして保存できるルーチンに整備して汎用性を確保しておきました。こういうのを作っておくと、あとになって地道に効いてくるはずです。たぶん・・・きっと。

実行すると、お手元の環境の「メモ」アプリの最新から2つ目のエントリの名称をファイル名にして、本文内容をデスクトップにPDFとRTFで保存します。

notes_entry.png

filenames.png

pdf.png

rtf.png

AppleScript名:Notes上の指定のエントリをPDFやRTFとして書き出す
– Created 2015-09-18 by Shane Stanley
– Modified 2015-09-18 by Takaaki Naganoya
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

set targFol to POSIX path of (path to desktop)

tell application “Notes”
  set theBody to body of note 2
  
set theName to name of note 2 – for file name
end tell

– Notesの本文をスタイル付きテキストに
set anNSString to current application’s NSString’s stringWithString:theBody
set theData to anNSString’s dataUsingEncoding:(current application’s NSUTF16StringEncoding) –日本語の環境&内容で検証ずみ。Chineseとかはどうか?
set styledString to current application’s NSAttributedString’s alloc()’s initWithHTML:theData documentAttributes:(missing value)

set aRes to my saveStyledTextAsPDF(theName, targFol, styledString)
–> true

set bRes to my saveStyledTextAsRTF(theName, targFol, styledString)
–> true

–スタイル付きテキストを指定フォルダ(POSIX path)にRTFで書き出し
on saveStyledTextAsRTF(aFileName, targFol, aStyledString)
  –Convert NSMutableStyledStrings to RTF
  
set bstyledLength to aStyledString’s |string|()’s |length|()
  
set bDict to current application’s NSDictionary’s dictionaryWithObject:“NSRTFTextDocumentType” forKey:(current application’s NSDocumentTypeDocumentAttribute)
  
set bRTF to aStyledString’s RTFFromRange:(current application’s NSMakeRange(0, bstyledLength)) documentAttributes:bDict
  
  
– build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“rtf”
  
  
return (bRTF’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsRTF

–スタイル付きテキストを指定フォルダ(POSIX path)にPDFで書き出し
on saveStyledTextAsPDF(aFileName, targFol, aStyledString)
  – get page size being used for printing
  
set printInfo to current application’s NSPrintInfo’s sharedPrintInfo()
  
set pageSize to printInfo’s paperSize()
  
set theLeft to printInfo’s leftMargin()
  
set theTop to printInfo’s topMargin()
  
  
– make a text view
  
set theView to current application’s NSTextView’s alloc()’s initWithFrame:{origin:{x:0, y:0}, |size|:pageSize}
  
theView’s setTextContainerInset:{theLeft, theTop}
  
  
– put in the text
  
theView’s textStorage()’s setAttributedString:aStyledString
  
set theData to theView’s dataWithPDFInsideRect:{origin:{x:0, y:0}, |size|:pageSize}
  
  
– build path based on title
  
set theName to current application’s NSString’s stringWithString:aFileName
  
set theName to theName’s stringByReplacingOccurrencesOfString:“/” withString:“_”
  
set theName to theName’s stringByReplacingOccurrencesOfString:“:” withString:“_”
  
set thePath to current application’s NSString’s stringWithString:targFol
  
set thePath to (thePath’s stringByAppendingPathComponent:theName)’s stringByAppendingPathExtension:“pdf”
  
  
return (theData’s writeToFile:thePath atomically:true) as boolean
end saveStyledTextAsPDF

★Click Here to Open This Script 

2015/08/20 ASOCで動的にWindowを作成

Cocoaの機能を用いて動的にWindowを作成し、メッセージを表示したあとにWindowを消すAppleScriptです。

dispcustomwin.png

Mac OS X登場当時から、こうしたカスタムメッセージ表示用の部品の必要性がひろくscripterに認識されており、さまざまな実装が試されたなか・・・OS Xのnotification center(display notificationでAppleScriptからも表示可能)に集約されていったという歴史があります。

notification.png

オリジナルは、edama2さんの「Okaeri(シンプル版)」のコードで、そこから大幅に機能を簡略化し、当時のCocoa AppleScript Appletから、OS X 10.10上のAppleScriptObjC向けに書き換えたものです。

dispcustomwin2_resized.png

AppleScript側から汎用的にメッセージを表示させるサブルーチンに変更してみました。かなり手軽に使えます。ASOCはARC環境で動いているので、Windowオブジェクトを明示的にReleaseしてあげる必要はないはずですが・・・さて?

# 連続して実行すると3回目に表示がおかしくなるのは、、、何か足りないかも、、、まだ油断できないレベルです

Shaneから「foreground/main threadから実行する必要があるよ」という指摘があり、ASObjC Explorer 4では問題なく連続して何回でも実行できることを確認。Script EditorだとCommand-Control-Rを実行して、表示がすぐに消えたりやっぱり3回目にScript Editorごとクラッシュしたりと不思議な現象が(ーー;;;

AppleScript名:ASOCで動的にWindowを作成
– Created 2012-06-13 by edama2
– Modified 2015-08-20 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

if not (current application’s NSThread’s isMainThread()) as boolean then
  display alert “This script must be run from the main thread (Command-Control-R in Script Editor).” buttons {“Cancel”} as critical
  
error number -128
end if

set aWin to makeWinWithMessage(“Piyomaru Software”, “Custom Message From Takaaki Naganoya”)
tell current application
  delay 5
end tell
my closeWin:aWin

–ウィンドウを作成
on makeWinWithMessage(aTitle, aMes)
  
  
set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {800, 250}}
  
set aBacking to current application’s NSTitledWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
– Window
  
set aWin to current application’s NSWindow’s alloc()
  (
aWin’s initWithContentRect:aFrame styleMask:aBacking backing:aDefer defer:false screen:aScreen) –’s autorelease()
  
aWin’s setBackgroundColor:(current application’s NSColor’s whiteColor())
  
  
aWin’s setTitle:aTitle
  
aWin’s setDelegate:me
  
aWin’s setDisplaysWhenScreenProfileChanges:true
  
aWin’s setHasShadow:true
  
aWin’s setIgnoresMouseEvents:true
  
aWin’s setLevel:(current application’s NSNormalWindowLevel)
  
aWin’s setOpaque:false
  
aWin’s setReleasedWhenClosed:true
  
aWin’s |center|()
  
aWin’s makeKeyAndOrderFront:(me)
  
  
– Custom View
  
set aCustView to current application’s NSView’s alloc()
  
aCustView’s initWithFrame:aFrame
  
aCustView’s setNeedsDisplay:true
  
set {origin:{x:x, y:y}, |size|:{width:w, height:h}} to aCustView’s |bounds|()
  
aWin’s setContentView:aCustView
  
  
– Text View
  
set aTV2 to current application’s NSTextView’s alloc()
  
  
set titleHeight to 26
  
set y2 to h - titleHeight - (titleHeight / 6)
  
set y3 to h - titleHeight
  
set y3 to h - y3 - (y3 / 6)
  
  
aTV2’s initWithFrame:{{0, y3}, {w, y2}}
  
aTV2’s insertText:aMes
  
aTV2’s setAlignment:(current application’s NSCenterTextAlignment)
  
aTV2’s setDrawsBackground:false
  
aTV2’s setEditable:false
  
aTV2’s setFont:(current application’s NSFont’s fontWithName:“HiraMinPro-W3″ |size|:72)
  
aTV2’s setSelectable:false
  
aTV2’s setTextColor:(current application’s NSColor’s blackColor())
  
aCustView’s addSubview:aTV2
  
  
–aWin’s setBackgroundColor:(current application’s NSColor’s clearColor())
  
  
return aWin
  
end makeWinWithMessage

–ウィンドウを閉じる
on closeWin:aWindow
  delay 3
  
repeat with n from 10 to 1 by -1
    (aWindow’s setAlphaValue:n / 10)
    
delay 0.02
  end repeat
  
aWindow’s |close|()
end closeWin:

★Click Here to Open This Script 

2012/12/15 AppleScriptObjCでAES128暗号化ライブラリを用いて暗号化/復号化

xcatsanさんが「AES128暗号化ライブラリ FBEncryptor」を公開されているのを見つけたので、AppleScriptObjCから呼び出して暗号化/復号化のテストを行ってみました。

とりあえず、記事にあったように必要なファイルを自分のAppleScriptObjCのプロジェクトにコピーして、AppleScriptObjCから呼び出してみました。

NSDataベースの暗号化/復号化はちょっと試してみてうまくインタフェースがとれなかったので、文字ベースの暗号化/復号化のメソッドを呼び出したら、うまくやりとりができました。

enc1.png

enc2.png

こんな風に、公開されているさまざまなObjective-CのコードをAppleScriptから呼び出せて、さらに他のアプリケーションをコントロールできると面白いですね。

→ Xcodeプロジェクトのダウンロード

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– encryptionTest

– Created by Takaaki Naganoya on 2012/12/14.
– Copyright (c) 2012年 Takaaki Naganoya. All rights reserved.
–  http://cocoadays.blogspot.jp/2011/06/ios-aes128-fbencryptor.html

script AppDelegate
  property parent : class “NSObject”
  
property FBEncryptorAES : current application’s class “FBEncryptorAES”
  
  property aKeyTF : missing value
  
property aTV : missing value
  
  property aButton : missing value
  
property bButton : missing value
  
  
  property encDecF : true
  
  
  
  on clicked_(sender)
    
    set aTag to tag of sender
    
set aTag to aTag as integer
    
    
    set textStorage to (my aTV’s textStorage())
    
set theText to textStorage’s |string|()
    
set aStr to theText as Unicode text
    
    –set aKeyPhrase to “KeyPhrase_YouMust_change”
    
    set aKeyPhrase to aKeyTF’s stringValue()
    
set aKeyPhrase to aKeyPhrase as Unicode text
    
    if aKeyPhrase = “” then
      tell current application to display dialog “Keyphrase Blank Error” buttons {“OK”} default button 1 with icon 1
      
return
    end if
    
    
    if aTag = 100 then
      
      set aRes to ectryptStr_Keyphrase_(aStr, aKeyPhrase)
      
aButton’s setEnabled_(false)
      
bButton’s setEnabled_(true)
      
    else if aTag = 200 then
      
      set aRes to decryptStr_Keyphrase_(aStr, aKeyPhrase)
      
aButton’s setEnabled_(true)
      
bButton’s setEnabled_(false)
      
    end if
    
    
    my aTV’s setString_(aRes)
    
  end clicked_
  
  
  
  –文字ベースの暗号化
  
on ectryptStr_Keyphrase_(aStr, aKeyPhrase)
    return FBEncryptorAES’s encryptBase64String_keyString_separateLines_(aStr, aKeyPhrase, true)
  end ectryptStr_Keyphrase_
  
  
  –文字ベースの復号化
  
on decryptStr_Keyphrase_(aStr, aKeyPhrase)
    return FBEncryptorAES’s decryptBase64String_keyString_(aStr, aKeyPhrase)
  end decryptStr_Keyphrase_
  
  
  
  
  
  on applicationWillFinishLaunching_(aNotification)
    
    aButton’s setEnabled_(true)
    
bButton’s setEnabled_(false)
    
  end applicationWillFinishLaunching_
  
  on applicationShouldTerminate_(sender)
    return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2012/06/13 おかえり(シンプル版)

読者の方(edama2さん)からの投稿です。以前に私がAppleScript Studioで作成して公開していた(る?)、スリープ解除検知&ユーザー通知アプリケーション「おかえり」の簡略版をMac OS X 10.7から作れるようになったAppleScriptエディタベースのAppleScriptObjCで作られました。

yyyeyoyycyaye-2012-06-13-02922.jpeg

yyyeyoyycyaye-2012-06-10-235739.jpeg

投稿していただいてから公開するまでに時間がかかってしまいましたが……実は、AppleScriptエディタベースのASOCのHTML書き出しツールを用意していなかったためで……ようやく、書き出し用のツール(AppleScriptで記述)を準備しました。

——
<edama2さんより>
今日のネタは「おかえり(シンプル版)」です。なかなか更新されない「おかえり」にいらだちを覚え、ついに自分で作り……というのは冗談で、「Cocoa-applescript aplet」の習作として作ってみました。

スリープの復帰の通知を受け取り、半透明のウインドウの表示と音を鳴らすだけです。誕生日とか正月だけの特別なウィンドウはありません。

ウインドウの色と音を変更できるようにしたいところですが、Xcodeを使わずコードだけでウィンドウを作るのは結構面倒だったのとシンプル版ということで省略しました。オリジナルの「おかえり」から「Twentieth Anniversary Macintosh.aiff」だけ使用させていただきました。

最初、同じスプリクト内にカスタムビューのコード(MyView.scpt)を書いていたのですが、初期化の際にエラーが出て難儀しました。どうやら別ファイルにしないと上手く初期化してくれないようです。

作成は10.7.4、テストは10.7.4と10.6.8でしました。ASOC Scriptの新規作成は10.7.4でないとできませんが、編集は書き方によっては10.6.8でもできました。

→ アプレット(編集可能)のダウンロード
</edama2さんより>

スクリプト名:おかえり(シンプル版)
property _sound_name : “Twentieth Anniversary Macintosh”

on run
  #通知の登録
  
tell current application’s NSWorkspace’s sharedWorkspace()
    tell notificationCenter()
      addObserver_selector_name_object_(me, “okaeri:”, “NSWorkspaceScreensDidWakeNotification”, missing value)
    end tell
  end tell
end run

on quit
  current application’s NSNotificationCenter’s defaultCenter()’s removeObserver_(me)
  
continue quit
end quit

#ウィンドウを表示→待機→閉じる
on okaeri_(sender)
  set pool to current application’s NSAutoreleasePool’s new() –>意味があるかよくわからないけどとりあえず。
  
  
copy makeWin() to okaeriWindow
  
  
set filePath to current application’s NSBundle’s mainBundle()’s pathForResource_ofType_(_sound_name, “aiff”)
  
current application’s NSSound’s alloc()’s initWithContentsOfFile_byReference_(filePath, true)’s play()
  
  
delay 5
  
  
closeWin_(okaeriWindow)
  
  
pool’s drain() –release()
end okaeri_

#ウィンドウを作成
on makeWin()
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {800, 250}}
  
set aBacking to current application’s NSBorderlessWindowMask
  
set aDefer to current application’s NSBackingStoreBuffered
  
  
tell current application’s NSWindow’s alloc()
    tell initWithContentRect_styleMask_backing_defer_screen_(aFrame, aBacking, aDefer, false, aScreen)’s autorelease()
      
      
#カスタムビュー
      
tell current application’s MyView’s alloc()
        tell initWithFrame_(aFrame)
          setNeedsDisplay_(true)
          
set aView to it
        end tell
      end tell
      
      
set {origin:{x:x, y:y}, |size|:{width:w, height:h}} to contentView()’s |bounds|()
      
set titleHeight to 26
      
set y2 to h - titleHeight - (titleHeight / 6)
      
      
#タイトルバー
      
set messageText to “スリープ復帰を検出しました(” & (current date) & “)” as text
      
tell current application’s NSTextView’s alloc()
        tell initWithFrame_({{0, y2}, {w, titleHeight}})
          insertText_(messageText)
          
setAlignment_(current application’s NSCenterTextAlignment)
          
setDrawsBackground_(false)
          
setEditable_(false)
          
setFont_(current application’s NSFont’s titleBarFontOfSize_(13))
          
setSelectable_(false)
          
setTextColor_(current application’s NSColor’s whiteColor())
          
aView’s addSubview_(it)
        end tell
      end tell
      
      
set y3 to h - titleHeight
      
set y3 to h - y3 - (y3 / 6)
      
      
#メッセージビュー
      
set myName to current application’s NSProcessInfo’s processInfo()’s environment()’s valueForKey_(”LOGNAME”) as text
      
set messageText to myName & “さん” & return & “おかえりなさい”
      
tell current application’s NSTextView’s alloc()
        tell initWithFrame_({{0, y3}, {w, y2}})
          insertText_(messageText)
          
setAlignment_(current application’s NSCenterTextAlignment)
          
setDrawsBackground_(false)
          
setEditable_(false)
          
setFont_(current application’s NSFont’s fontWithName_size_(”HiraMinPro-W3″, 72))
          
setSelectable_(false)
          
setTextColor_(current application’s NSColor’s whiteColor())
          
aView’s addSubview_(it)
        end tell
      end tell
      
      
#ウィンドウの設定
      
setBackgroundColor_(current application’s NSColor’s clearColor())
      
setContentView_(aView)
      
setDelegate_(me)
      
setDisplaysWhenScreenProfileChanges_(true)
      
setHasShadow_(true)
      
setIgnoresMouseEvents_(not false)
      
setLevel_((current application’s NSScreenSaverWindowLevel) + 10000)
      
setOpaque_(false)
      
setReleasedWhenClosed_(true)
      
|center|()
      
makeKeyAndOrderFront_(me)
      
      
return it
    end tell
  end tell
end makeWin

#ウィンドウを閉じる
on closeWin_(aWindow)
  tell aWindow
    repeat with n from 10 to 1 by -1
      setAlphaValue_(n / 10)
      
delay 0.02
    end repeat
    
|close|()
  end tell
end closeWin_

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:MyView
script MyView
  property parent : class “NSView”
  
  
on drawRect_(rect)
    
    
–log my |bounds|()
    
set {origin:{x:x, y:y}, |size|:{width:w, height:h}} to my |bounds|()
    
set titleHeight to 26
    
    
set thePath to current application’s NSBezierPath’s bezierPath()
    
    
#タイトルバー
    
set aFrame to {{0, h - titleHeight}, {w, titleHeight}}
    
set aPath to current application’s NSBezierPath’s bezierPathWithRect_(aFrame)
    
set strartColor to current application’s NSColor’s blackColor()’s colorWithAlphaComponent_(0.4)
    
set endColor to current application’s NSColor’s blackColor()’s colorWithAlphaComponent_(0.8)
    
tell current application’s NSGradient’s alloc()
      tell initWithStartingColor_endingColor_(strartColor, endColor)
        drawInBezierPath_angle_(aPath, 270)
      end tell
    end tell
    
thePath’s appendBezierPath_(aPath)
    
    
#メッセージ
    
set aFrame to {{0, 0}, {w, h - titleHeight}}
    
set aPath to current application’s NSBezierPath’s bezierPathWithRect_(aFrame)
    
set strartColor to current application’s NSColor’s blueColor()’s colorWithAlphaComponent_(0.4)
    
set endColor to current application’s NSColor’s blueColor()’s colorWithAlphaComponent_(0.8)
    
tell current application’s NSGradient’s alloc()
      tell initWithStartingColor_endingColor_(strartColor, endColor)
        drawInBezierPath_angle_(aPath, 270)
      end tell
    end tell
    
thePath’s appendBezierPath_(aPath)
    
  end drawRect_
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

スクリプト名:CocoaAppletAppDelegate.scpt

– CocoaAppletAppDelegate.applescript
– Cocoa-AppleScript Applet

– Copyright 2011 {Your Company}. All rights reserved.

– This application delegate emulates the OSA script applet by loading “main.scpt” from the
– “Scripts” folder in the application resources and invoking the traditional run/open/reopen/quit
– handlers in response to Cocoa application delegate methods being called.

– This is provided in source form so that you may customize or replace it if your needs go
– beyond the basic applet handlers.

– Some of these methods must guard against re-entrancy, because invoking the main.scpt
– handler may end up invoking the event handler inherited from the current application,
– which calls the application delegate’s method again.

script CocoaAppletAppDelegate
  property parent : class “NSObject”
  
property mainScript : missing value – the applet’s main.scpt
  
property didOpenFiles : false – true = the application opened documents during startup
  
property isOpeningFiles : false – re-entrancy guard: true = in the process of opening files
  
property isReopening : false – re-entrancy guard: true = in the process of re-opening
  
property isQuitting : false – re-entrancy guard: true = in the process of quitting
  
  
on applicationWillFinishLaunching_(aNotification)
    – Insert code here to initialize your application before any files are opened
    
    
– Emulate an OSA Applet: Load the main script from the Scripts resource folder.
    
try
      set my mainScript to load script (path to resource “main.scpt” in directory “Scripts”)
    on error errMsg number errNum
      – Perhaps this should silently fail if it can’t load the script; that way, a Cocoa applet
      
– can just have Cocoa classes and no main.scpt.
      
display alert “Could not load main.scpt” message errMsg & ” (” & errNum & “)” as critical
    end try
  end applicationWillFinishLaunching_
  
  
on applicationDidFinishLaunching_(aNotification)
    – Insert code here to do startup actions after your application has initialized
    
    
if mainScript is missing value then return
    
    
– Emulate an OSA Applet: Invoke the “run” handler.
    
    
– If we have already opened files during startup, don’t invoke the run handler.
    
if didOpenFiles then return
    
    
try
      tell mainScript to run
    on error errMsg number errNum
      if errNum is not -128 then
        display alert “An error occurred while running” message errMsg & ” (” & errNum & “)” as critical
      end if
    end try
    
    
– TODO: Read the applet’s “stay open” flag and quit if it’s false or unspecified.
    
– For now, all Cocoa Applets stay open and require the run handler to explicitly quit,
    
– which is arguably more correct for a Cocoa application, anyway.
    
(* if not shouldStayOpen then
      quit
    end if *)
  end applicationDidFinishLaunching_
  
  
on applicationShouldHandleReopen_hasVisibleWindows_(sender, flag)
    – Insert code here to perform actions in response to a “reopen” event
    
    
if mainScript is missing value then return true
    
    
– Guard against re-entrancy.
    
if not isReopening then
      set isReopening to true
      
      
– Emulate an OSA Applet: Invoke the “reopen” handler. If there isn’t one, let the application object
      
– handle reopen (this is different from an OSA applet, which would do nothing if there is no handler;
      
– this way, the application will perform the usual “create untitled document” behavior by default).
      
try
        tell mainScript to reopen
        
set isReopening to false
        
        
return false
      on error errMsg number errNum
        if errNum is not -128 then
          display alert “An error occurred while reopening” message errMsg & ” (” & errNum & “)” as critical
        end if
      end try
      
      
set isReopening to false
    end if
    
    
return true
  end applicationShouldHandleReopen_hasVisibleWindows_
  
  
on application_openFiles_(sender, filenames)
    – Insert code here to perform actions in response to an “open documents” event
    
    
– Remember that we opened files, to avoid invoking the “run” handler later.
    
set didOpenFiles to true
    
    
– Guard against re-entrancy.
    
if not isOpeningFiles and mainScript is not missing value then
      set isOpeningFiles to true
      
      
try
        – Convert all the filenames from NSStrings to script strings
        
set theFilenameStrings to {}
        
repeat with eachFile in filenames
          set theFilenameStrings to theFilenameStrings & (eachFile as text)
        end repeat
        
        
tell mainScript to open theFilenameStrings
        
set isOpeningFiles to false
        
        
tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplySuccess)
      on error errMsg number errNum
        if errNum = -128 then
          tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyCancel)
        else
          display alert “An error occurred while opening file(s)” message errMsg & ” (” & errNum & “)” as critical
          
tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyFailure)
        end if
      end try
      
      
set isOpeningFiles to false
    else
      tell sender to replyToOpenOrPrint_(current application’s NSApplicationDelegateReplyFailure)
    end if
  end application_openFiles_
  
  
on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
    
– Guard against re-entrancy.
    
if not isQuitting and mainScript is not missing value then
      set isQuitting to true
      
      
– Emulate an OSA Applet: Invoke the “quit” handler; if the handler returns, it has fully
      
– handled the quit message and we should not quit, otherwise, it calls “continue quit”,
      
– which returns error -10000.
      
try
        tell mainScript to quit
        
set isQuitting to false
        
        
return current application’s NSTerminateCancel
      on error errMsg number errNum
        – -128 means there is no quit handler
        
– -10000 means the handler did “continue quit”
        
if errNum is not -128 and errNum is not -10000 then
          display alert “An error occurred while quitting” message errMsg & ” (” & errNum & “)” as critical
        end if
      end try
      
      
set isQuitting to false
    end if
    
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

オリジナルの「おかえり」のコアコードは10行ぐらいで、このサンプルよりもはるかに単純な原理で動いています。
いまから10年近く前にすでに動いていたもので、オリジナルコードはAppleScriptだけで記述。公開版は透明ウィンドウを付けるため(だけ)にAppleScript Studioで開発しました。

「おかえり」のアップデートが止まっていたのは、自分が欲しい機能をてんこ盛りに盛り込んで……画面をInterface Builder上でデザインした時点で「こんなに大量のGUI部品のコードを書くのは大変」なことに気づき……そのまま放置状態に陥ってしまったためでしょう(Piyocastをはじめ、個人的な優先順位の高い自作の未公開アプリがいくつもあるので)。

アプリが自分自身のコード量で自滅した、といえなくもありません。

当時は、Mac AppStoreも存在していませんでしたし、フリーで配布するにはバージョンアップに手がかかりすぎる自作ソフト群にうんざりしていた、ということもあります。

いまだったら、AppleScriptObjCならGUI部品のサポートコードを書くのもそれほど手間ではないので、バージョンアップして公開してみてもよいかもしれません。

2012/03/11 NSTextViewからのテキストデータ取得、テキスト設定サンプル

NSTextViewへのデータ設定、データ取得を行うAppleScriptObjCのサンプルです。

AppleScript Studioで作ってあったOpenSSLのユーティリティをAppleScriptObjCで作り直そうとしたときに、どうも一定文字以上のデータのエンコード時に文字化けが発生。その問題検証のために作成したサンプルです。

実際に試してみて、NSTextViewからの値の取得/設定時にはとくに問題がないことがはっきりしました。やはり、実際に組んで試してみないと。

tv1.jpg

→ プロジェクトのダウンロード(Xcode 4.1 on Mac OS X 10.6.8で検証)

AppleScriptObjCファイル名:textview1AppDelegate.applescript

– textview1AppDelegate.applescript
– textview1

– Created by 長野谷 隆昌 on 12/01/13.
– Copyright 2012 Piyomaru Software. All rights reserved.

script textview1AppDelegate
  
property parent : class “NSObject”
  
  
property aTV : missing value
  
property bTV : missing value
  
  
on applicationWillFinishLaunching_(aNotification)
    
– Insert code here to initialize your application before any files are opened
  
end applicationWillFinishLaunching_
  
  
on applicationShouldTerminate_(sender)
    
– Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  
end applicationShouldTerminate_
  
  
on clicked_(sender)
    
    
set textStorage to (my aTV’s textStorage())
    
set theText to textStorage’s |string|()
    
display dialog (theText as string)
    
  
end clicked_
  
  
on clicked2_(sender)
    
    
    
set textStorage to (my aTV’s textStorage())
    
set theText to textStorage’s |string|()
    
    
set theText to theText as Unicode text
    
    
my bTV’s setString_(theText)
    
  
end clicked2_
  
  
on clicked3_(sender)
    
    
set textStorage to (my aTV’s textStorage())
    
set theTextA to textStorage’s |string|()
    
set theTextA to theTextA as Unicode text
    
    
set textStorage to (my bTV’s textStorage())
    
set theTextB to textStorage’s |string|()
    
set theTextB to theTextB as Unicode text
    
    
if theTextA = theTextB then
      
display dialog “左右のテキスト内容はイコールです”
    
else
      
display dialog “左右のテキスト内容は合っていません”
    
end if
    
  
end clicked3_
  
end script

▼新規書類に ▼カーソル位置に ▼ドキュメント末尾に

2011/02/16 TextViewの内容を取得する

AppleScriptObjCでTextViewからテキストを取得するサンプルです。

→ ダウンロード