— Created 2019-10-15 by Takaaki Naganoya
— 2019 Piyomaru Software
use AppleScript version "2.5"
use scripting additions
use framework "Foundation"
use framework "AppKit"
property NSFont : a reference to current application’s NSFont
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 NSButton : a reference to current application’s NSButton
property NSOnState : a reference to current application’s NSOnState
property NSOffState : a reference to current application’s NSOffState
property NSTextField : a reference to current application’s NSTextField
property NSMutableArray : a reference to current application’s NSMutableArray
property NSButtonTypeOnOff : a reference to current application’s NSButtonTypeOnOff
property NSMutableDictionary : a reference to current application’s NSMutableDictionary
property NSRunningApplication : a reference to current application’s NSRunningApplication
property NSFontAttributeName : a reference to current application’s NSFontAttributeName
property NSKernAttributeName : a reference to current application’s NSKernAttributeName
property NSMutableParagraphStyle : a reference to current application’s NSMutableParagraphStyle
property NSLigatureAttributeName : a reference to current application’s NSLigatureAttributeName
property NSMutableAttributedString : a reference to current application’s NSMutableAttributedString
property NSUnderlineStyleAttributeName : a reference to current application’s NSUnderlineStyleAttributeName
property NSParagraphStyleAttributeName : a reference to current application’s NSParagraphStyleAttributeName
property NSForegroundColorAttributeName : a reference to current application’s NSForegroundColorAttributeName
property theResult : 0
property returnCode : 0
property bArray : {} –Checkbox button object array
property tYear : 0
property tMonth : 0
property theAlert : missing value
property theView : missing value
on run
set tYear to 2019
set tMonth to 11
set ignoreP to true
set ndList to {2, 3, 4, 9, 10, 13, 16, 17, 23, 24, 25, 30} –選択表示させない日付
set paramObj to {myMessage:"", mySubMessage:"適切な日付を以下からえらんでください", targetYear:tYear, targetMonth:tMonth, nodisp:ndList, ignorePast:ignoreP}
–Detect Past Date Error
set curDate to current date
set dLimit to getMlen(tYear, tMonth) of me
set tmpDate to getDateInternational(tYear, tMonth, dLimit) of me
if (tmpDate < curDate) and (ignoreP = true) then error (("Target month is past (" & tYear as string) & "/" & tMonth as string) & "/1 is past. Today is " & date string of curDate & ")"
–my chooseItemByCheckBox:paramObj –for Debugging
my performSelectorOnMainThread:"chooseItemByCheckBox:" withObject:(paramObj) waitUntilDone:true
return my sort1DNumList:(my theResult) ascOrder:true
–> {1, 3, 5, 7, 9, 11}
end run
on chooseItemByCheckBox:(paramObj)
set aMainMes to (myMessage of paramObj) as string
set aSubMes to (mySubMessage of paramObj) as string
set aMatList to (matrixTitleList of paramObj) as list
set tYear to (targetYear of paramObj) as integer
set tMonth to (targetMonth of paramObj) as integer
set noDispList to (nodisp of paramObj) as list
set ignoreP to (ignorePast of paramObj) as boolean
if aMainMes = "" then
set aMainMes to "日付を選択してください"
end if
set theView to makeCalendarView(tYear, tMonth, noDispList, ignoreP) of me
–Select the first radio button item
set my theResult to {}
— 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:theView
–for Help Button
–its setShowsHelp:(true)
its setDelegate:(me)
set aWin to its |window|()
end tell
aWin’s setLevel:(current application’s NSFloatingWindowLevel)
— show alert in modal loop
NSRunningApplication’s currentApplication()’s activateWithOptions:0
my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true
if (my returnCode as number) = 1001 then error number -128
end chooseItemByCheckBox:
on doModal:aParam
set (my returnCode) to aParam’s runModal()
end doModal:
on clicked:aParam
set aTag to (tag of aParam) as integer
–clicked
if aTag is not in (my theResult) then
set the end of (my theResult) to aTag
else
set theResult to my deleteItem:aTag fromList:theResult
end if
end clicked:
on deleteItem:anItem fromList:theList
set theArray to NSMutableArray’s arrayWithArray:theList
theArray’s removeObject:anItem
return theArray as list
end deleteItem:fromList:
–1D List(数値)をsort / ascOrderがtrueだと昇順ソート、falseだと降順ソート
on sort1DNumList:theList ascOrder:aBool
tell current application’s NSSet to set theSet to setWithArray_(theList)
tell current application’s NSSortDescriptor to set theDescriptor to sortDescriptorWithKey_ascending_(missing value, true)
set sortedList to theSet’s sortedArrayUsingDescriptors:{theDescriptor}
return (sortedList) as list
end sort1DNumList:ascOrder:
–Help Button Clicked Event Handler
on alertShowHelp:aNotification
set aRes to display dialog "Do you change all checkbox state?" buttons {"All Off", "All On", "Cancel"} default button 3 with icon 1
set bRes to (button returned of aRes) as string
if bRes = "All Off" then
set bLen to bArray’s |count|()
set theResult to {}
repeat with i from 0 to bLen
((bArray’s objectAtIndex:i)’s setState:(current application’s NSOffState))
end repeat
else if bRes = "All On" then
set bLen to bArray’s |count|()
set theResult to {}
repeat with i from 0 to bLen
((bArray’s objectAtIndex:i)’s setState:(current application’s NSOnState))
set the end of theResult to i + 1
end repeat
end if
return false –trueを返すと親ウィンドウ(アラートダイアログ)がクローズする
end alertShowHelp:
–書式つきテキストを組み立てる
on makeRTFfromParameters(aStr as string, fontName as string, aFontSize as real, aKerning as real, aLineSpacing as real)
set aVal1 to NSFont’s fontWithName:fontName |size|:aFontSize
set aKey1 to (NSFontAttributeName)
set aVal2 to NSColor’s blackColor()
set aKey2 to (NSForegroundColorAttributeName)
set aVal3 to aKerning
set akey3 to (NSKernAttributeName)
set aVal4 to 0
set akey4 to (NSUnderlineStyleAttributeName)
set aVal5 to 2 –all ligature ON
set akey5 to (NSLigatureAttributeName)
set aParagraphStyle to NSMutableParagraphStyle’s alloc()’s init()
aParagraphStyle’s setMinimumLineHeight:(aLineSpacing)
aParagraphStyle’s setMaximumLineHeight:(aLineSpacing)
set akey7 to (NSParagraphStyleAttributeName)
set keyList to {aKey1, aKey2, akey3, akey4, akey5, akey7}
set valList to {aVal1, aVal2, aVal3, aVal4, aVal5, aParagraphStyle}
set attrsDictionary to NSMutableDictionary’s dictionaryWithObjects:valList forKeys:keyList
set attrStr to NSMutableAttributedString’s alloc()’s initWithString:aStr attributes:attrsDictionary
return attrStr
end makeRTFfromParameters
on makeNSTextField(xPos as integer, yPos as integer, myWidth as integer, myHeight as integer, editableF as boolean, setVal as string, backgroundF as boolean, borderedF as boolean)
set aNSString to NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(xPos, yPos, myWidth, myHeight))
aNSString’s setEditable:(editableF)
aNSString’s setStringValue:(setVal)
aNSString’s setDrawsBackground:(backgroundF)
aNSString’s setBordered:(borderedF)
return aNSString
end makeNSTextField
–指定月のカレンダーを1D List(7 days x 6 weeks) で返す
on retListCalendar(tYear, tMonth)
set mLen to getMlen(tYear, tMonth) of me
set aList to {}
set fDat to getDateInternational(tYear, tMonth, 1) of me
tell current application
set aOffset to (weekday of fDat) as number
end tell
–header gap
repeat (aOffset – 1) times
set the end of aList to ""
end repeat
–calendar body
repeat with i from 1 to mLen
set the end of aList to (i as string)
end repeat
–footer gap
repeat (42 – aOffset – mLen + 1) times
set the end of aList to ""
end repeat
return aList
end retListCalendar
–現在のカレンダーで指定年月の日数を返す(国際化対応版)
on getMlen(aYear as integer, aMonth as integer)
set theNSCalendar to current application’s NSCalendar’s currentCalendar()
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:1 hour:0 minute:0 |second|:0 nanosecond:0
set theResult to theNSCalendar’s rangeOfUnit:(current application’s NSDayCalendarUnit) inUnit:(current application’s NSMonthCalendarUnit) forDate:theDate
return |length| of theResult
end getMlen
–現在のカレンダーで指定年月のdate objectを返す
on getDateInternational(aYear, aMonth, aDay)
set theNSCalendar to current application’s NSCalendar’s currentCalendar()
set theDate to theNSCalendar’s dateWithEra:1 |year|:aYear |month|:aMonth |day|:aDay hour:0 minute:0 |second|:0 nanosecond:0
return theDate as date
end getDateInternational
–ローカライズされた曜日名称を返す
on getLocalizedDaynames(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s standaloneWeekdaySymbols() as list
return dayNames
end getLocalizedDaynames
–ローカライズされた月名称を返す
on getLocalizedMonthnames(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set monthNames to df’s standaloneMonthSymbols() as list
return monthNames
end getLocalizedMonthnames
–ローカライズされた曜日の名称を返す
on getLocalizedWeekdaySymbol(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s weekdaySymbols()
return dayNames as list
end getLocalizedWeekdaySymbol
–ローカライズされた曜日の名称(短縮版)を返す
on getLocalizedShortWeekdaySymbol(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s shortWeekdaySymbols()
return dayNames as list
end getLocalizedShortWeekdaySymbol
–ローカライズされた曜日の名称(短縮記号)を返す
on getLocalizedVeryShortWeekdaySymbol(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s veryShortWeekdaySymbols()
return dayNames as list
end getLocalizedVeryShortWeekdaySymbol
–ローカライズされた曜日の名称を返す
on getLocalizedVeryStandaloneWeekdaySymbols(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s standaloneWeekdaySymbols()
return dayNames as list
end getLocalizedVeryStandaloneWeekdaySymbols
–ローカライズされた曜日の名称を返す
on getLocalizedShortStandaloneWeekdaySymbols(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s shortStandaloneWeekdaySymbols()
return dayNames as list
end getLocalizedShortStandaloneWeekdaySymbols
–ローカライズされた曜日の名称を返す
on getLocalizedVeryShortStandaloneWeekdaySymbols(aLoc)
set df to current application’s NSDateFormatter’s alloc()’s init()
df’s setLocale:(current application’s NSLocale’s localeWithLocaleIdentifier:aLoc)
set dayNames to df’s veryShortStandaloneWeekdaySymbols()
return dayNames as list
end getLocalizedVeryShortStandaloneWeekdaySymbols
–カレンダー表示ビューを作成
on makeCalendarView(tYear as integer, tMonth as integer, noDispList as list, ignoreP as boolean)
set colNum to 7
set rowNum to 8
set aLen to (colNum * rowNum)
set aButtonCellWidth to 70 –56
set aButtonCellHeight to 40
set viewWidth to aButtonCellWidth * colNum
set viewHeight to aButtonCellHeight * rowNum
–define the matrix size where you’ll put the radio buttons
set matrixRect to current application’s NSMakeRect(0.0, 0.0, viewWidth, viewHeight)
set aView to NSView’s alloc()’s initWithFrame:(matrixRect)
set aCount to 1
set aFontSize to 30
set bArray to current application’s NSMutableArray’s new()
–Make Header (Month, Year)
set x to 1
set tmpB to (NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum) * (aButtonCellHeight), aButtonCellWidth * 4, aButtonCellHeight)))
(tmpB’s setEditable:false)
(tmpB’s setBordered:false)
(tmpB’s setDrawsBackground:false)
(tmpB’s setAlignment:(current application’s NSLeftTextAlignment))
(tmpB’s setStringValue:((tYear as string) & " / " & tMonth as string))
(tmpB’s setFont:(NSFont’s fontWithName:"Times-Roman" |size|:40))
(bArray’s addObject:tmpB)
set aCount to aCount + 1
–Make Header (Weekday)
set curLocale to current application’s NSLocale’s currentLocale()
set aDS10 to (curLocale’s objectForKey:(current application’s NSLocaleIdentifier)) as string
set wdList to getLocalizedShortStandaloneWeekdaySymbols(aDS10) of me
set y to 2
repeat with x from 1 to 7
set j to contents of item x of wdList
set tmpB to (NSTextField’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum – 1) * (aButtonCellHeight), aButtonCellWidth, aButtonCellHeight / 2)))
(tmpB’s setEditable:false)
(tmpB’s setAlignment:(current application’s NSCenterTextAlignment))
(tmpB’s setStringValue:(j))
(bArray’s addObject:tmpB)
end repeat
set aCalList to retListCalendar(tYear, tMonth) of me
set aCount to 1
–Make Calendar (Calendar Body)
set curDat to current date
repeat with y from 3 to rowNum
repeat with x from 1 to colNum
set j to contents of item aCount of aCalList
set tmpB to (NSButton’s alloc()’s initWithFrame:(current application’s NSMakeRect(((x – 1) * aButtonCellWidth), ((aLen – aCount) div colNum – 2) * aButtonCellHeight, aButtonCellWidth, aButtonCellHeight)))
set tmpDate to getDateInternational(tYear, tMonth, j as integer) of me
set tmpF to (tmpDate < curDat) as boolean
if ignoreP = false then
set dispF to true
else if ignoreP = true and tmpF = false then
set dispF to true
else
set dispF to false
end if
if (j as integer) is not in noDispList then
if (dispF = true) then
(tmpB’s setTitle:(j as string))
(tmpB’s setFont:(NSFont’s fontWithName:"ArialMT" |size|:aFontSize))
–set attrTitle to makeRTFfromParameters((aCount as string), "ArialMT", aFontSize, 0, (aFontSize * 1.2)) of me
–(tmpB’s setAttributedTitle:(attrTitle))
(tmpB’s setShowsBorderOnlyWhileMouseInside:true)
(tmpB’s setAlignment:(current application’s NSCenterTextAlignment))
(tmpB’s setEnabled:(j ≠ ""))
(tmpB’s setTarget:me)
(tmpB’s setAction:("clicked:"))
(tmpB’s setButtonType:(NSButtonTypeOnOff))
(tmpB’s setHidden:(j = ""))
if j is not equal to "" then
(tmpB’s setTag:(j))
(bArray’s addObject:tmpB)
end if
end if
end if
set aCount to aCount + 1
end repeat
end repeat
(aView’s setSubviews:bArray)
return aView
end makeCalendarView