Archive for the 'NSTextField' Category

2017/07/16 ASOCでcolor popup buttonを作成

動的にWindow+View+popup buttonを作成し、色選択を行うpopup menuを作成するAppleScriptです。

color_popup.png

Script Editor上でControl-Command-Rと操作することで実行できます。アプレットとして保存して実行してもOKです。

color_popup2.png

いくつか候補がある色のうちからどれかを選ぶといった処理は割とあるのですが、色のプレビューを行うインタフェースはAppleScriptのデフォルトのコマンドでは用意されていないので、ちょっと作ってみました。

たとえば、テキストエディット上で資料の文章をチェックを行なっているような場合、見直す必要のある箇所に赤く色をつけておいて、赤くマークした箇所のみAppleScriptで抽出するとかいう処理は便利にやっています(ものすごく効率がいい)。赤以外でもマークした箇所を抽出するとかいったら、本Scriptのような部品を利用して「どの色でマークした箇所を抽出しようか」文章中の色付き部分を全部スキャンしたうえで色選択という処理ができるわけです。

Script EditorおよびASObjC Explorer 4上での実行は確認できていますが、Script Debugger 6.0.5 試用版ではクラッシュします。

1枚のみのWindowを作成する場合にはNSWindowControllerを用いる必要はないようですが、ためしにNSWindowControllerを省いたScriptも作って試してみたところ・・・安定性がやや損なわれるようでした。結局、NSWindowControllerがあったほうがよいのでは???

指定色でNSImageを作成してmenu itemに設定していますが、macOS 10.13ではこれが正方形でないとおもいどおりのサイズでメニューに表示されませんでした。

color_popup1013.png
▲本ScriptをmacOS 10.13で動かしたときのイメージ(10.12上で再現)

color_popup1013b.png
▲macOS 10.13上のpopup menu上で大きくColor部分を表示するときには、imageの縦横サイズを同じに?

AppleScript名:ASOCでcolor popup buttonを作成
– Created 2017-07-15 by Takaaki Naganoya
– 2017 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”
use framework “Carbon” – AEInteractWithUser() is in Carbon
–http://piyocast.com/as/archives/4724

property windisp : false
property wController : false –いらなかったかも?

if current application’s AEInteractWithUser(-1, missing value, missing value) is not equal to 0 then return

set ap1List to {{65535, 0, 65535}, {0, 32896, 16448}, {0, 32896, 65535}, {19702, 31223, 40505}}

set aButtonMSG to “OK”
set aSliderValMSG to “Select Color”
set aVal to getPopupValues(ap1List, 65535, aButtonMSG, aSliderValMSG, 20) of me

on getPopupValues(ap1List, aColMax, aButtonMSG, aSliderValMSG, timeOutSecs)
  
  
set (my windisp) to true
  
  
set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 360, 100))
  
  
–Labelをつくる
  
set a1TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(30, 60, 80, 20))
  
a1TF’s setEditable:false
  
a1TF’s setStringValue:“Color:”
  
a1TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set a1Button to current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 60, 200, 20)) pullsDown:false
  
a1Button’s removeAllItems()
  
  
set a1Menu to current application’s NSMenu’s alloc()’s init()
  
  
set iCount to 0
  
repeat with i in ap1List
    copy i to {r1, g1, b1}
    
    
set nsCol to makeNSColorFromRGBAval(r1, g1, b1, aColMax, aColMax) of me
    
set anImage to makeNSImageWithFilledWithColor(64, 16, nsCol) of me
    
    
set aTitle to “col_test_” & (iCount as string)
    
set aMenuItem to (current application’s NSMenuItem’s alloc()’s initWithTitle:aTitle action:“actionHandler:” keyEquivalent:“”)
    (
aMenuItem’s setImage:anImage)
    (
aMenuItem’s setEnabled:true)
    (
a1Menu’s addItem:aMenuItem)
    
    
set iCount to iCount + 1
  end repeat
  
  
a1Button’s setMenu:a1Menu
  
  
  
–Buttonをつくる
  
set bButton to (current application’s NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(80, 10, 140, 40)))
  
bButton’s setButtonType:(current application’s NSMomentaryLightButton)
  
bButton’s setBezelStyle:(current application’s NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:(“clicked:”)
  
bButton’s setKeyEquivalent:(return)
  
  
aView’s addSubview:a1TF
  
  
aView’s addSubview:a1Button
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた(いらない?)
  
set aWin to (my makeWinWithView(aView, 300, 100, aSliderValMSG))
  
  
set wController to current application’s NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 100
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.01
    
set aCount to aCount - 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to a1Button’s titleOfSelectedItem() as string
  else
    set s1Val to false
  end if
  
  
return s1Val
  
end getPopupValues

on clicked:aSender
  set (my windisp) to false
end clicked:

–make Window for Display
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
  
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)
  
–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 setReleasedWhenClosed:true
  
aWin’s |center|()
  
–aWin’s makeKeyAndOrderFront:(me)
  
  
aWin’s setContentView:aView
  
  
return aWin
  
end makeWinWithView

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

–Popup Action Handler
on actionHandler:sender
  set aTag to tag of sender as integer
  
set aTitle to title of sender as string
end actionHandler:

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 current application’s NSColor’s colorWithCalibratedRed:aRedCocoa green:aGreenCocoa blue:aBlueCocoa alpha:aAlphaCocoa
  
return aColor
end makeNSColorFromRGBAval

–指定サイズの画像を作成し、指定色で塗ってファイル書き出し
on makeNSImageWithFilledWithColor(aWidth, aHeight, fillColor)
  set anImage to current application’s NSImage’s alloc()’s initWithSize:(current application’s NSMakeSize(aWidth, aHeight))
  
anImage’s lockFocus()
  

  
set theRect to {{x:0, y:0}, {height:aHeight, width:aWidth}}
  
set theNSBezierPath to current application’s NSBezierPath’s bezierPath
  
theNSBezierPath’s appendBezierPathWithRect:theRect
  

  
fillColor’s |set|() –色設定
  
theNSBezierPath’s fill() –ぬりつぶし
  

  
anImage’s unlockFocus()
  

  
return anImage
end makeNSImageWithFilledWithColor

★Click Here to Open This Script 

2015/12/30 Popup Buttonを作成

Cocoaの機能を用いてWindowを作成し、その上に2つのポップアップボタン(NSPopUpButton)を配置。指定のArrayでポップアップメニューを作成して、選択結果を取得するAppleScriptです。

but1.png

but2.png

but3.png

たとえばNumbers/Excelスプレッドシート上の2つのセルの値を入れ替えるような処理が必要だったとして、Pure AppleScriptでchoose from listコマンドを2回実行すれば2つのセルを指定できます。ただ、それだと実際の使い勝手はいまいちです。

Xcode上でAppleScriptObjCのプログラムを書けば、完全なGUIを作成できますが、Xcodeで作成したASOCのプログラムはランタイムの挙動が若干(Script Editor上で記述したASOCとは)異なり、また生産性もいまひとつです。

そこで、「ちょっとしたGUI」であれば、AppleScriptのプログラム中で記述したりライブラリから呼び出したりできたほうが便利なケースが多いものと思われます。本Scriptはそうした用途のためのテストプログラムです。

実行時には、Script Editor上ではControl-Command-Rを実行してください。

AppleScript名:ASOCでpopup buttonを作成
– Created 2015-12-30 by Takaaki Naganoya
– 2015 Piyomaru Software
use AppleScript version “2.4″
use scripting additions
use framework “Foundation”
use framework “AppKit”

property windisp : false
property wController : false

set ap1List to {“Alpha”, “Bravo”, “Charlie”, “Delta”, “Echo”, “Foxtrot”, “Golf”, “Hotel”, “India”}
set ap2List to {“Juliett”, “Kilo”, “Lima”, “Mike”, “November”, “Oscar”, “Papa”, “Quebec”, “Romeo”}

set aButtonMSG to “OK”
set aSliderValMSG to “Numbers上の値を交換するセルの選択”
set aVal to getPopupValues(ap1List, ap2List, aButtonMSG, aSliderValMSG, 20) of me
–>  {”Alpha”, “Kilo”}–操作した場合
–>  {false, false}–タイムアウト時

on getPopupValues(ap1List, ap2List, aButtonMSG, aSliderValMSG, timeOutSecs)
  
  
set (my windisp) to true
  
  
set aView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, 360, 120))
  
  
–Labelをつくる
  
set a1TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(60, 110, 80, 20))
  
set a2TF to current application’s NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(60, 70, 80, 20))
  
a1TF’s setEditable:false
  
a2TF’s setEditable:false
  
a1TF’s setStringValue:“移動前:”
  
a2TF’s setStringValue:“移動後:”
  
a1TF’s setDrawsBackground:false
  
a2TF’s setDrawsBackground:false
  
a1TF’s setBordered:false
  
a2TF’s setBordered:false
  
  
–Ppopup Buttonをつくる
  
set a1Button to current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(140, 110, 180, 20)) pullsDown:false
  
set a2Button to current application’s NSPopUpButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(140, 70, 180, 20)) pullsDown:false
  
  
a1Button’s removeAllItems()
  
a2Button’s removeAllItems()
  
  
a1Button’s addItemsWithTitles:ap1List
  
a2Button’s addItemsWithTitles:ap2List
  
  
  
–Buttonをつくる
  
set bButton to (current application’s NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(110, 10, 180, 40)))
  
bButton’s setButtonType:(current application’s NSMomentaryLightButton)
  
bButton’s setBezelStyle:(current application’s NSRoundedBezelStyle)
  
bButton’s setTitle:aButtonMSG
  
bButton’s setTarget:me
  
bButton’s setAction:(“clicked:”)
  
bButton’s setKeyEquivalent:(return)
  
  
aView’s addSubview:a1TF
  
aView’s addSubview:a2TF
  
  
aView’s addSubview:a1Button
  
aView’s addSubview:a2Button
  
aView’s addSubview:bButton
  
aView’s setNeedsDisplay:true
  
  
–NSWindowControllerを作ってみた
  
set aWin to (my makeWinWithView(aView, 400, 160, aSliderValMSG))
  
set wController to current application’s NSWindowController’s alloc()
  
wController’s initWithWindow:aWin
  
  
wController’s showWindow:me
  
  
set aCount to timeOutSecs * 10
  
  
set hitF to false
  
repeat aCount times
    if (my windisp) = false then
      set hitF to true
      
exit repeat
    end if
    
delay 0.1
    
set aCount to aCount - 1
  end repeat
  
  
my closeWin:aWin
  
  
if hitF = true then
    set s1Val to a1Button’s titleOfSelectedItem() as string
    
set s2Val to a2Button’s titleOfSelectedItem() as string
  else
    set {s1Val, s2Val} to {false, false}
  end if
  
  
return {s1Val, s2Val}
  
end getPopupValues

on clicked:aSender
  set (my windisp) to false
end clicked:

–make Window for Display
on makeWinWithView(aView, aWinWidth, aWinHeight, aTitle)
  set aScreen to current application’s NSScreen’s mainScreen()
  
set aFrame to {{0, 0}, {aWinWidth, aWinHeight}}
  
  
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)
  
–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 setReleasedWhenClosed:true
  
aWin’s |center|()
  
–aWin’s makeKeyAndOrderFront:(me)
  
  
aWin’s setContentView:aView
  
  
return aWin
  
end makeWinWithView

–close win
on closeWin:aWindow
  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 

2013/10/10 AppleScriptObjCで複数項目選択可能なポップアップボタンを

AppleScriptObjCのプログラムで、複数項目が選択可能なポップアップボタンを作ってみました。

作ってみましたといっても、ポップアップボタンは、ボタンをクリックすると表示されるメニュー項目のうち、選択状態にあるものをボタンのタイトルとして表示するというものであり、複数項目の選択はできません。

mpop9.png

できないながらも、どーにかして複数項目選択できるようにしなくてはならない(このへん、海外のクライアントの要望)ということで、NSPopupButtonをそのままで使うことは無理です。

そこで、NSPopupButtonをクリックすると表示されるメニューの方をなんとかしてしまえ、ということになります(このあたりまでは、海外のサイトでもよく話が出ている)。

メニューとしてNSCustomViewとかNSBoxあたりを指定する、というのがだいたいのオチなのですが……実際に試してみると、言うほど簡単ではありません。

さらにメニューに表示させる項目の数を動的に変化させたいという話もあり、メニューとして表示させるビューの大きさの制御とか、NSMatrixの位置をNSCustomViewやNSBox内のどこを基準に寄せるかといった話をクリアしなくてはなりません。

popup1.png

結局、それが面倒だったので、NSMatrixを直接メニューとして指定して表示させるようにしてみました。

popup2.png

これなら、NSMatrixを載せている「下地」との位置関係やサイズの調整などを一切行わなくてすむために、楽にできました。

そこまでクリアしても、まだ大変なことが続きます。

メニューで複数項目を選択できるところまではなんとかクリアしたのですが、その選択内容をポップアップボタンのタイトルに指定すると……メニュー内に新たな選択項目として追加されてしまうのでした。

……いろいろ思い悩んだ結果、クライアントには「勘弁してください」と泣きつき、この「複数項目選択可能なポップアップボタン」はお蔵入りに。

正確にいうと、ポップアップボタンにわざわざしなくても、ウィンドウ上にふつーにチェックボックスとして並べれば、その方が確実だしよいのではないか、という提案を行いました。

ところが、その翌日にはなんとか動くところまで持って行けました。結局、ポップアップボタンに選択状態を表示させるとメニューに追加されてしまうので、選択内容を別の部品に表示させることに。

枠や下地の描画をやめて、マウスクリックを無視するように設定して、ポップアップボタンの上に載せておけば、まるでポップアップボタンに選択状態を表示している……かのように見えるはずです。

mpop1.png
▲ビルドして起動したところ

mpop2.png
▲「+」ボタンをクリックしてテーブル内の行を追加し、それぞれにデータを入力

mpop3.png
▲ひととおりメニューに表示する項目を入力し終わったら、「Reflect」ボタンをクリック。これで、テーブルの内容をもとにポップアップメニューを動的に作成

mpop4.png
▲テーブル内容をもとに作成されたポップアップメニュー

mpop6.png
▲メニュー内の複数項目を選択できる

mpop7.png
▲複数選択した状態を別のテキストフィールド上に表示

→ Xcodeプロジェクトのダウンロード(69KB)

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– ViewInMenu

– Created by Takaaki Naganoya on 2013/10/08.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
  property pu : missing value – IBOutlet for the popUpButton
  
property item1 : missing value
  
property mat : missing value – IBOutlet for the matrix of NSLabels
  
  property theData : {} – the table data
  
property theArrayController : missing value
  
property aTable : missing value
  
  property aTextF : missing value
  
  
  
  
  
  on applicationWillFinishLaunching_(aNotification)
    
    set theData to {}
    
    set item1 to current application’s NSMenuItem’s alloc()’s initWithTitle_action_keyEquivalent_(“”, missing value, “”)
    
item1’s setView_(mat)
    
item1’s setTarget_(me)
    
pu’s removeAllItems()
    
pu’s |menu|()’s addItem_(item1)
    
    aTextF’s setStringValue_(“”)
    
  end applicationWillFinishLaunching_
  
  
  
  
  
  on applicationShouldTerminate_(sender)
    return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
  
  
  
  on matrixClick_(sender) – IBAction for the matrix
    
    aTextF’s setStringValue_(“”)
    
    tell theArrayController
      set outList to arrangedObjects() as list
    end tell
    
    set aLen to length of outList
    
set aList to {}
    
    
    repeat with i from 0 to (aLen - 1)
      
      set aTmpVal to mat’s cellAtRow_column_(i, 0)’s integerValue()
      
set aTmpVal to aTmpVal as number
      
      if aTmpVal is equal to 1 then
        
        set aTmpText to mat’s cellAtRow_column_(i, 0)’s title()
        
set the end of aList to aTmpText
        
      end if
      
    end repeat
    
    set aText to retArrowText__(aList, “, “)
    
set aText to aText as string
    
    aTextF’s setStringValue_(aText)
    
  end matrixClick_
  
  
  
  
  –Array Controllerから動的にメニューを作成する
  
on buttonClick_(sender) – IBAction for the button
    
    set outList to {}
    
    tell theArrayController
      set theList to arrangedObjects() as list
    end tell
    
    log {“theList”, theList}
    
    repeat with i in theList
      set j to contents of i
      
set jj to aTitle of j
      
set jj to jj as string
      
set the end of outList to jj
    end repeat
    
    set aLen to length of outList
    
    
    mat’s renewRows_columns_(aLen, 1)
    
mat’s sizeToCells()
    
    repeat with i from 0 to (aLen - 1)
      set aStr to contents of item (i + 1) of outList
      
set aStr to aStr as string
      
mat’s cellAtRow_column_(i, 0)’s setTitle_(aStr)
    end repeat
    
    
    aTextF’s setStringValue_(“”)
    
  end buttonClick_
  
  
  –リストを任意のデリミタ付きでテキストに
  
on retArrowText__(aList, aDelim)
    
    set aText to “”
    
set aLen to length of aList
    
set aCount to 1
    
    repeat with i in aList
      set j to i as string
      
      if aCount < aLen then
        set aText to aText & j & aDelim
      else
        set aText to aText & j
      end if
      
      set aCount to aCount + 1
      
    end repeat
    
    return aText
    
  end retArrowText__
  
  
  
  
end script

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

2013/09/24 AppleScriptObjCでCore Animation

AppleScriptObjCで、CoreAnimationを使用してLine(ほっそいNSBox)を360度回転させるサンプルです。

ani4.png
▲こういうひとたちです(Line=ほっそいNSBox)

AppleScriptObjCでCoreAnimationを利用する方法をいろいろ探していて、ようやくサンプルを見つけていじくっていました。一番大変だったのは、Viewに対するCore Animationの有効設定をXcode上で行う方法を見つけること。

ani2.png

ani3.png

これだけ(↑)。

XcodeのInterface Builderで「Core Animation Layer」にチェックを入れるだけ。これだけです。

AppleScriptObjCとCore Animationというと、月とスッポン、水と油ぐらい世界が違うもので……本当に探すのに苦労しました(結局、MacScripter.netにあったのを見つけられなかっただけでした、、)。

ani.png
▲反時計まわりに、おおよそ1回転まわります

ただ、360度回してみようとしているのですが、きっちり360度は回ってないですね(誤差として許容され得るものか、、、)。試行錯誤の最中です。

→ Xcodeプロジェクトのダウンロード(64KB)

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– vAnimation

– Created by Takaaki Naganoya on 2013/09/23.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  
  property parent : class “NSObject”
  
property aTextField : missing value
  
  property arrow : missing value – IBOutlet for a long narrow NSBox
  
  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 awakeFromNib()
    –arrow’s layer()’s setAnchorPoint_({0.5, 0.5})
    
arrow’s layer()’s setAnchorPoint_({0.5, 1.0})
    
set xValue to (arrow’s layer()’s superlayer()’s |bounds|()’s |size|()’s width) / 2
    
    –set yValue to (arrow’s layer()’s superlayer()’s |bounds|()’s |size|()’s height) / 2
    
set yValue to (arrow’s layer()’s superlayer()’s |bounds|()’s |size|()’s height)
    
–arrow’s layer()’s setPosition_({xValue, yValue})
    
  end awakeFromNib
  
  
  on click_(sender)
    
    set ctx to current application’s NSAnimationContext’s currentContext()
    
–ctx’s setDuration_(0.1)
    
    repeat with i from 0 to 63 by 1
      
      set curI to (i / 10) as real
      
      aTextField’s setStringValue_(curI as string)
      
      arrow’s layer()’s setValue_forKeyPath_(curI, “transform.rotation”) – Rotation by degrees counterclockwise
      
      tell current application
        delay 0.1
      end tell
      
    end repeat
    
  end click_
  
end script

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

2013/09/06 ASOCでカレンダー作成・表示テスト

AppleScriptで作成したさまざまな部品を組み合わせて、AppleScriptObjCでカレンダー表示を行ってみました。

単に、NSMatrixの中にNSButtonを作っておいて、リストのカレンダーを順次流し込んでいます。

calt1.png
▲サンプルの画面

calt3.png
▲後日、Xcode上でデザインをブラッシュアップしたもの(作業途上)

出来上がりもたいしたことはなく、記述量も大したことはありませんが、割とdateの扱いで苦労しています。

ASOCでは、dateオブジェクトの扱いがややめんどうで、current applicationへのtellブロック内でしか正常に機能しませんし、ハンドラ間でdateオブジェクトの受け渡しを行うのはエラーの元になります。

そんなわけで、dateオブジェクトを裸のままで扱わず、局所的にdateオブジェクトを生成しては必要な情報を取り出すという、かなりめんどうな取扱いを行っています。

かといって、NSDateやNSCalendarを使うのも……たった曜日の情報を欲しいだけなのにどれだけ記述させたら気がすむんだと呆れるほどのプログラムになってしまうので、見送りました。いいフレームワークがあれば使わないでもないですが、OSバージョンが上がるたびにメンテナンスする必要があることを考えると、ASのdateオブジェクトを使ったほうが、まだ手軽です。

→ Xcodeプロジェクトのダウンロード(82KB)

2013/02/11 AppleScriptObjCでMyriad Helpersの三角関数を使ってWindowを円運動

AppleScriptObjCで、三角関数を使ってWindowを円運動させるサンプルです。

三角関数を使ってWindowを円軌道(純粋な円運動だと見栄えがしないので楕円にしていますが)で動かすという、きわめて基礎的な処理です。

curculwin.png

Objective-Cのプログラム内ではsin/cos/tanを使えるものの、AppleScriptObjCプログラム内ではこれらの関数は使えません。

Shane StanleyによるAppleScriptObjCのバイブル「AppleScriptObjC Explored」に、AppleScriptObjCから使うと便利な……逆をいえばAppleScriptObjCの弱点を補うためのObjective-Cのコード「Myriad Helpers」が含まれています。dateの変換や取得、alias→URL変換、そしてこの三角関数(sin/cos/tan/asin/acos/atan/sinh/cosh/tanh/asinh/acosh/atanh/log/log10)の呼び出しなどがそれです。

この「Myriad Helpers」のv2.0がmacosxautomation.comのサイト上からダウンロードできるようになっています

Sal SoghoianとShane Stanleyの合作によるとおぼしきこのAppleScript情報サイト「macosxautomation.com」、本来「AppleScriptObjC Explored」を買わないと入手できない「Myriad Helpers」をなぜフリーでダウンロードできるようにしてあるのか、どういう取引が2者の間で行われたかをいろいろ考えてしまうものですが……フリーで配布しているので、これを使ったサンプルプロジェクトを公開しても問題はないということに。

興味深いのは、この「Myriad Helpers v2.0」がgarbage-collectedなプロジェクトでもAutomatic Reference Countingが有効になっているプロジェクトに組み込んでもビルドできること(正確にいえば、それをわざわざ明記してあること)。

次のOS X 10.9で提供されるAppleScriptObjCの処理系はAutomatic Reference Countingが有効になっているプロジェクトが前提になるだろう、ということが伺われます。ただ、Mac OS X 10.6までさかのぼってその変更が反映されるかどうか……といったところでしょうか。実際問題、AppleScriptObJCのプロジェクトにさまざまなObjective-Cのプログラムを突っ込んで利用するような場合に、garbage-collectedな設定でビルドできないフレームワークなどもあったりして、解決してほしい問題の筆頭であることも事実です。

最初のサンプルは、clicked_ハンドラで連続してウィンドウを円運動させるもの。ウィンドウ上のテキストフィールド上に入れた数値を半径とした円運動を行わせます。ただし、1回だけ。

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

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– circulateWin

– Created by Takaaki Naganoya on 2013/02/11.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
property aWin : missing value
  
  property ObjWithF : missing value
  
property aStrF : 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 {origin:{x:n, y:m}, |size|:{|width|:n2, height:m2}} to (aWin’s frame()) as record
    
    set aNum to aStrF’s doubleValue()
    
set aNum to aNum as number
    
    
    repeat with i from 1 to 360 by 1
      
      set aSin to ObjWithF’s fordTrig_({“sin”, i, true})
      
set aCos to ObjWithF’s fordTrig_({“cos”, i, true})
      
      set x to ((aNum * aSin) + aNum) * 2
      
set y to (aNum * aCos) + aNum
      
      aWin’s setFrame_display_animate_({{x, y}, {200, 200}}, true, true)
      
      
    end repeat
    
  end clicked_
  
  
end script

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

もうひとつは、0.1秒ごとのタイマー割り込みで円運動させるもの。割り込みで処理するので、それなりのCPUパワーとそれなりのGPUを積んでいれば、マシンに対する負荷もそれほど大きくないでしょう。

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

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– circulateWin

– Created by Takaaki Naganoya on 2013/02/11.
– Copyright (c) 2013年 Takaaki Naganoya. All rights reserved.


script AppDelegate
  property parent : class “NSObject”
  
property aWin : missing value
  
  property ObjWithF : missing value
  
property aStrF : missing value
  
  property NSTimer : class “NSTimer”
  
property aDegree : 1
  
  
  property aNum : 0
  
  on applicationWillFinishLaunching_(aNotification)
    
    set aDegree to 1
    
    
  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 {origin:{x:n, y:m}, |size|:{|width|:n2, height:m2}} to (aWin’s frame()) as record
    
    set aNum to aStrF’s doubleValue()
    
set aNum to aNum as number
    
    NSTimer’s scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0.1, me, “timer1Fired:”, “Whatever”, true)
    
    
  end clicked_
  
  
  
  on timer1Fired_(sender)
    
    set aDegree to incrementDegree_(aDegree)
    
    set aSin to ObjWithF’s fordTrig_({“sin”, aDegree, true})
    
set aCos to ObjWithF’s fordTrig_({“cos”, aDegree, true})
    
    set x to ((aNum * aSin) + aNum) * 2
    
set y to (aNum * aCos) + aNum + 100
    
    aWin’s setFrame_display_animate_({{x, y}, {200, 200}}, true, true)
    
    
  end timer1Fired_
  
  
  on incrementDegree_(aDeg)
    if aDeg > 360 then
      set aDeg to 1
    else
      return (aDeg + 1)
    end if
  end incrementDegree_
end script

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

2012/12/28 AppleScriptObjCでボタンの文字色を変更

最初はAppleScriptObjCでWindowのタイトルの文字色を変更できないか試していたのですが、それが(かなり組まないと)ムリだと気付き……逆に、簡単に文字色を変更できるGUI部品がないかテストした試作品です。

NSAttributedStringがどのGUI部品に対して設定可能なのか、APIのドキュメントをキーワード検索して調べました。

coloredb.png

NSTextFieldの中身は当然として、NSButtonのほかNSMenuの内容などに色つき文字(NSAttributedString)を指定できることが分り、とりあえず調査はこのぐらいにしておきました。試作プロジェクトの「WindowTitleTest」はWindowのタイトル色を変更できないか試していた頃の名残りです。

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

AppleScriptObjCファイル名:AppDelegate.applescript

– AppDelegate.applescript
– windowTitleTest

– Created by Takaaki Naganoya on 2012/12/25.
– Copyright (c) 2012年 Takaaki Naganoya. All rights reserved.
– original http://www.macscripter.net/viewtopic.php?id=38088

script AppDelegate
  
  property parent : class “NSObject”
  
  property nsc : class “NSColor”
  
  property tf : missing value
  
property aWin : missing value
  
property aButton : missing value
  
  
  on applicationWillFinishLaunching_(aNotification)
    
    –set colorArray to current application’s NSArray’s arrayWithObjects_(nsc’s redColor(),nsc’s orangeColor(),nsc’s yellowColor(),nsc’s greenColor(),nsc’s blueColor,nsc’s purpleColor(),missing value)
    
    
    tell current application’s NSColorList to set AppleColors to colorListNamed_(“Apple”)
    
set redColor to AppleColors’s colorWithKey_(“Red”)
    
tell current application’s NSFont to set myFont to fontWithName_size_(“HiraKakuPro-W6″, 24)
    
    set attrsDict to current application’s NSDictionary’s dictionaryWithObjects_forKeys_({myFont, redColor}, {current application’s NSFontAttributeName, current application’s NSForegroundColorAttributeName})
    
tell current application’s NSAttributedString to set aString to alloc()’s initWithString_attributes_(“色つき文字を設定できるGUI部品のテスト”, attrsDict)
    
    
    tf’s setAttributedStringValue_(aString) –NSTextField
    
aButton’s setAttributedTitle_(aString) –NSButton
    
  end applicationWillFinishLaunching_
  
  
  on applicationShouldTerminate_(sender)
    – Insert code here to do any housekeeping before your application quits
    
return current application’s NSTerminateNow
  end applicationShouldTerminate_
  
end script

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

2012/03/07 テキストへの色指定サンプル

テキストに色指定を行うサンプルのAppleScriptObjCプログラムです。

textcol.jpg

AppleScriptObjCファイル名:textcolorTestAppDelegate.applescript

– textcolorTestAppDelegate.applescript
– textcolorTest

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

script textcolorTestAppDelegate
  
property parent : class “NSObject”
  
  
property nsc : class “NSColor”
  
property tf : missing value
  
property aTextField : missing value
  
  
on applicationWillFinishLaunching_(aNotification)
    
    
–ひとつめのNSTextField(入力フィールド)
    
set aString to current application’s NSMutableAttributedString’s alloc()’s initWithString_(“これはテスト用の文字列ですよー”)
    
    
set colorArray to current application’s NSArray’s arrayWithObjects_(nsc’s redColor(), nsc’s orangeColor(), nsc’s yellowColor(), nsc’s greenColor(), nsc’s blueColor, nsc’s purpleColor(), missing value)
    
    
repeat with i from 0 to (aString’s |length|()) - 1
      
aString’s addAttribute_value_range_(current application’s NSForegroundColorAttributeName, colorArray’s objectAtIndex_(i mod 6), {i, 1})
    
end repeat
    
    
tf’s setAttributedStringValue_(aString)
    
    
    
–ふたつめのNSTextField(Label)
    
set bString to current application’s NSMutableAttributedString’s alloc()’s initWithString_(“●私のユーザー名”)
    
    
set colorArray to current application’s NSArray’s arrayWithObjects_(nsc’s redColor(), nsc’s blackColor())
    
    
set bLen to bString’s |length|()
    
    
bString’s addAttribute_value_range_(current application’s NSForegroundColorAttributeName, colorArray’s objectAtIndex_(0), {0, 1})
    
bString’s addAttribute_value_range_(current application’s NSForegroundColorAttributeName, colorArray’s objectAtIndex_(1), {1, (bLen - 1)})
    
    
aTextField’s setAttributedStringValue_(bString)
    
  
end applicationWillFinishLaunching_
  
  
  
  
on applicationShouldTerminate_(sender)
    
return current application’s NSTerminateNow
  
end applicationShouldTerminate_
  
  
end script

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

2012/03/07 指定のRGBカラーをGeneric CMYKプロファイルでCMYKに変換して……RGB値を取得

指定のRGBカラー値をGeneric CMYKプロファイルを用いてCMYK変換し、CMYK値を取り出そうとして……できなかったので仕方なくRGB値を取り出したAppleScriptObjCのプログラムです。

上のColorWellをクリックして任意の色(ここではライトグリーン)を選択。

asoc1.jpg

「Convert RGB to CMYK」ボタンをクリックすると、Mac OS XのGeneric CMYK Profileに基づいてCMYK変換を行い、下のColorWellに色を設定します。

asoc2.jpg

いい感じのCMYKっぽい色に変換されるのですが、ここからCMYK値を取り出すのに失敗(なんでだ〜)。仕方なくRGB値を取り出しています。

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

AppleScriptObjCファイル名:rgb2cmykAppDelegate.applescript

– rgb2cmykAppDelegate.applescript
– rgb2cmyk

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

– generic CMYK color Spaceを用いて、RGB→CMYK変換を行い、ColorWellにCMYKベースで色をセットしたあとRGB値でその色を取り出す
– 

script rgb2cmykAppDelegate
  
  
property parent : class “NSObject”
  
  
property rgbWell : missing value
  
property rgbR : missing value
  
property rgbG : missing value
  
property rgbB : missing value
  
  
property cmykWell : missing value
  
property cmykC : missing value
  
property cmykM : missing value
  
property cmykY : missing value
  
property cmykK : 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)
    
    
–RGB Color Wellのカラー値を読み取って、TextFieldに文字を入れる
    
set {rNum, gNum, bNum, aNum} to retColData(rgbWell)
    
    
set rNumStr to (rNum as integer) as string
    
set gNumStr to (gNum as integer) as string
    
set bNumStr to (bNum as integer) as string
    
    
rgbR’s setStringValue_(rNumStr)
    
rgbG’s setStringValue_(gNumStr)
    
rgbB’s setStringValue_(bNumStr)
    
    
    
–RGB Colorwellからカラーを読み取る
    
set tmpColor to rgbWell’s |color|
    
    
–Generic ProfileでRGB to CMYK変換してColorWellに設定
    
set cmykColSpace to current application’s NSColorSpace’s genericCMYKColorSpace
    
set color1 to tmpColor’s colorUsingColorSpace_(cmykColSpace)
    
    
    
–cmykWell’s setColor_(color1)
    
tell cmykWell
      
setColor_(color1)
    
end tell
    
    
    
–とりあえずRGBAでデータを取り出してみる
    
set {temp21, temp22, temp23, temp24} to retColData(cmykWell)
    
    
set temp21 to temp21 as string
    
set temp22 to temp22 as string
    
set temp23 to temp23 as string
    
set temp24 to temp24 as string
    
    
–TextFieldにCMYKデータを入れる
    
cmykC’s setStringValue_(temp21)
    
cmykM’s setStringValue_(temp22)
    
cmykY’s setStringValue_(temp23)
    
cmykK’s setStringValue_(temp24)
    
  
end clicked_
  
  
  
  
–指定オブジェクトのカラー値を取得する
  
on retColData(aObject)
    
    
–色空間のコンバートを行ってカラー値を取得する(強制的にRGB)
    
set tmpColor to aObject’s |color|
    
set color1 to tmpColor’s colorUsingColorSpaceName_(current application’s NSCalibratedRGBColorSpace)
    
    
set temp11 to color1’s redComponent()
    
set temp12 to color1’s greenComponent()
    
set temp13 to color1’s blueComponent()
    
set temp14 to color1’s alphaComponent()
    
    
–RGBAの並びでデータを返す
    
set TheColor to {(temp11 * 255) as integer, (temp12 * 255) as integer, (temp13 * 255) as integer, (temp14 * 255) as integer}
    
    
return TheColor
  
end retColData
  
  
  
end script

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

2011/01/16 TextFieldの表示/非表示設定

NSTextFieldの表示/非表示を行うサンプルです。

→ hidetf.zip

2011/01/16 NSTextFieldからの文字列取得/文字列設定

ASOCでNSTextFieldへのアクセスを行うサンプルです。

 set a to textField1’s stringValue() –textFieldからの文字列の取得
 textField2’s setStringValue_(a) –textFieldへの文字列の設定

→ twotextfield.zip