Problem with date picker showing (main thread issue?) - applescript

Working with an AppleScript file from https://github.com/bat-tomr/dialog-node ...
# 06/04/16 09:35:02
# Author: Shane Stanley
# Adapted by Christopher Stone
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
my datePicker()
on datePicker()
set theApp to path to frontmost application as text
if not (current application's NSThread's isMainThread()) as boolean then
display alert "This script must be run from the main thread." buttons {"Cancel"} as critical
error number -128
end if
-- create a view
set theView to current application's NSView's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, 100, 175))
-- create date picker
set datePicker to current application's NSDatePicker's alloc()'s initWithFrame:(current application's NSMakeRect(0, 0, 100, 100))
-- set style: choices are NSTextFieldAndStepperDatePickerStyle, NSClockAndCalendarDatePickerStyle, or NSTextFieldDatePickerStyle
#datePicker's setDatePickerStyle:(current application's NSClockAndCalendarDatePickerStyle)
datePicker's setDatePickerStyle:(current application's NSTextFieldAndStepperDatePickerStyle)
#datePicker's setDatePickerStyle:(current application's NSTextFieldDatePickerStyle)
-- set elements: choices include NSHourMinuteDatePickerElementFlag, NSHourMinuteSecondDatePickerElementFlag, NSTimeZoneDatePickerElementFlag, NSYearMonthDatePickerElementFlag, and NSEraDatePickerElementFlag
datePicker's setDatePickerElements:((current application's NSYearMonthDayDatePickerElementFlag) + (current application's NSHourMinuteSecondDatePickerElementFlag as integer))
-- set initial date
#datePicker's setDateValue:(current application's NSDate's |date|())
--set theCal var to a new(empty) instance of the calendar
set theCal to current application's class "NSCalendar"'s currentCalendar()
-- unpack the components of theCal to a variable
set theComponents to theCal's components:254 fromDate:(current application's NSDate's |date|())
theComponents's setSecond:0
theComponents's setMinute:0
theComponents's setHour:12
theComponents's setYear:2015
theComponents's setMonth:4
theComponents's setDay:1
datePicker's setDateValue:(theCal's dateFromComponents:theComponents)
-- get the size it needs
set theSize to datePicker's fittingSize()
--resize the picker and view accordingly
theView's setFrameSize:theSize
datePicker's setFrameSize:theSize
-- add the picker to the view
theView's setSubviews:{datePicker}
-- create an alert
set theAlert to current application's NSAlert's alloc()'s init()
-- set up alert
tell theAlert
its setMessageText:"Pick a date and time"
its setInformativeText:"Any date"
its addButtonWithTitle:"OK"
its addButtonWithTitle:"Cancel"
its setAccessoryView:theView
end tell
-- show alert in modal loop
set returnCode to theAlert's runModal()
if returnCode = (current application's NSAlertSecondButtonReturn) then error number -128
-- retrieve date
#set theDate to datePicker's dateValue() as date
# Shane Stanley
# http://macscripter.net/viewtopic.php?pid=119633#p119633
set theDate to datePicker's dateValue()
#set theCal to current application's class "NSCalendar"'s currentCalendar()
-- unpack the components of theDate to a variable
set theComponents to theCal's components:254 fromDate:theDate
set theDate to current date
set day of theDate to 1 -- important
set seconds of theDate to theComponents's |second|()
set year of theDate to theComponents's |year|()
set month of theDate to theComponents's |month|()
set day of theDate to theComponents's |day|()
set hours of theDate to theComponents's hour()
set minutes of theDate to theComponents's minute()
return (theDate as text)
#return (theDate)
end datePicker
The date picker does not display (at least on Mojave). It does display, however, if I put a display alert before runModal (but not otherwise).
I understand this may have to do with a need for performSelectorOnMainThread in latter Mac OSX versions, but if that is the case, I was not able to add it such that the code would work. Any ideas?

Here you go... Not much to say really. I basically just rewrote it because I can't stand messy code:
# 06/04/16 09:35:02
# Author: Shane Stanley
# Adapted by Christopher Stone
# Fixed & Rewritten by CJK
--------------------------------------------------------------------------------
use framework "AppKit"
use scripting additions
property this : a reference to the current application
property nil : a reference to missing value
property _1 : a reference to reference
property NSAlert : a reference to NSAlert of this
property NSDatePicker : a reference to NSDatePicker of this
property NSView : a reference to NSView of this
property NSAlertSecondButtonReturn : 1001
property NSHourMinuteSecondDatePickerElementFlag : 14
property NSTextFieldAndStepperDatePickerStyle : 0
property NSYearMonthDayDatePickerElementFlag : 224
--------------------------------------------------------------------------------
property date : missing value
--------------------------------------------------------------------------------
on run
its performSelectorOnMainThread:("showDatePicker:") withObject:{¬
NSTextFieldAndStepperDatePickerStyle, ¬
NSYearMonthDayDatePickerElementFlag + ¬
NSHourMinuteSecondDatePickerElementFlag} ¬
waitUntilDone:true
return my date
end run
on showDatePicker:params
local params
set {PickerStyle, PickerElements} to params
tell (current date) to set ¬
[dateFrom, day, its month, day, year, time] to ¬
[it, 1, 4, 1, 2015, 12 * hours + 0 * minutes]
tell NSDatePicker's alloc()
initWithFrame_({{0, 0}, {100, 100}})
setDatePickerStyle_(PickerStyle)
setDatePickerElements_(PickerElements)
setDateValue_(dateFrom)
set fittingSize to fittingSize()
setFrameSize_(fittingSize)
set View to NSView's alloc()
View's initWithFrame:{{0, 0}, {100, 175}}
View's setFrameSize:fittingSize
View's addSubview:it
tell NSAlert's alloc()
init()
setMessageText_("Pick a date and time")
setInformativeText_("Any date")
addButtonWithTitle_("OK")
addButtonWithTitle_("Cancel")
setAccessoryView_(View)
runModal()
end tell
set my date to dateValue() as date
end tell
end showDatePicker:
---------------------------------------------------------------------------❮END❯
System info: AppleScript version: 2.7 System version: 10.13.6

Related

MacOS: How to update an AppDelegate property via editing a table view cell?

In my macOS app I’m trying to update an AppDelegate property by editing a Table View Cell.
I created a sample project (Table View example project with array controller) using tips from the answer to this post.
I’m using macOS Big Sur (11.6.8) and Xcode 12.5.1. I'll be glad to supply a source archive download link or email it if requested. When I tried to add a link in this post it was rejected.
Here's my AppDelegate script:
script AppDelegate
property parent : class "NSObject"
property msg : ""
-- IBOutlets
property theWindow : missing value
property tableViewData : missing value
property arrayController : missing value
property showTableViewData : missing value
on `applicationWillFinishLaunching_(aNotification)`
appInit()
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
return current application's NSTerminateNow
end applicationShouldTerminate_
on appInit()
set my msg to (current date & return & return & "Initializing…") as string
delay .5
initTableView()
set my msg to (current date & return & return & "Ready.") as string
delay .5
end appInit
on initTableView()
set my tableViewData to {}
set my tableViewData to {{adName:("C21 ad" as string), pageNumber:("001" as string)}, {adName:("ERA ad" as string), pageNumber:("002" as string)}}
end initTableView
on `showTableViewData_(sender)`
set my msg to (current date & return & return & "showing tableViewData....") as string
delay .5
set displayText to ""
repeat with thisRecord in tableViewData
display alert "adName: " & (adName of thisRecord as string) & return & "pageNumber: " & (pageNumber of thisRecord as string)
end repeat
set my msg to (current date & return & return & "Ready.") as string
delay .5
end `showTableViewData_`
end script
How it works
As you can see I have hardcoded two records which I use to populate the tableViewData property on initialization which in turn is displayed in the table view. For some reason the adName data is not being displayed, but that bug is not what this post is about.
App initialized
Clicking the button reads the tableViewData property, iterates the records displaying them via an alert (so we can see it's contents).
Record display
Aside from the adName not displaying, so far so good.
Next, I edit the pageNumber table view cell for the first record (changing it from "001" to "777" and hitting return). When I click the button the first record is displayed which still shows a pageNumber value of "001" (instead of the "777" value I entered).
Record display after editing
Here are some shots of the table view cell attributes, connections, and bindings:
Attributes
Connections
Bindings
I tried selecting the bindings setting "Continuously Updates Value" but that doesn't seem to help; my tableViewData property is not updated with the newly entered data in the table view cell.
Most of the current developer docs use Obj-C or Swift instead of AppleScript and iOS or tvOS related. I'm using Xcode 12.5.1 because of problems binding UI elements to my code.
Thanks for taking the time to look this over.
The contents of tableViewData doesn't change but content of arrayController does. Try
repeat with thisRecord in content of arrayController
display alert "adName: " & (adName of thisRecord as string) & return & "pageNumber: " & (pageNumber of thisRecord as string)
end repeat
To make it work, use a Script Object instead of a record.
on makeAd(nameOfAd, pageNr)
script ad
property adName: nameOfAd
property pageNumber: pageNr
end script
return ad
end makeAd
on initTableView()
set my tableViewData to {makeAd("C21 ad", "001"), makeAd("ERA ad", "002")}
end initTableView

Multipage tiff to pdf with a script

I'm trying to make a pdf of a multipage tiff file. We tried this solution on a newer version of macOS and it worked. Can someone else help me to fine tune this?
After the conversion I like to rejoin the two separate pdf's to one file and I want to run it automatacily when a file is added to a certain folder.
Create hot folder on your Mac. Attach following script to it. The script will convert 1 multipage TIFF to 1 multipage PDF, at once:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "QuartzCore"
use framework "Quartz"
use framework "AppKit"
property |NSURL| : a reference to current application's |NSURL|
property NSString : a reference to current application's NSString
property PDFPage : a reference to current application's PDFPage
property NSImage : a reference to current application's NSImage
property PDFDocument : a reference to current application's PDFDocument
property NSBitmapImageRep : a reference to current application's NSBitmapImageRep
on adding folder items to this_folder after receiving these_items
set aRes to convertMultiPageTiffToPDF(item 1 of these_items) of me
end adding folder items to
on convertMultiPageTiffToPDF(anAlias)
--Make Output Path
set b to POSIX path of anAlias
set bb to changeExtensionInPath("pdf", b) --OutPath
--Read Multi-Page TIFF
set aURL to |NSURL|'s fileURLWithPath:b
set aImage to NSImage's alloc()'s initWithContentsOfURL:aURL
set aRawimg to aImage's TIFFRepresentation()
set eachTiffPages to (NSBitmapImageRep's imageRepsWithData:aRawimg) as list
--Make Blank PDF
set aPDFdoc to PDFDocument's alloc()'s init()
set pageNum to 0
repeat with curPage in eachTiffPages
set thisImage to contents of curPage
set aImg to (NSImage's alloc()'s initWithSize:(thisImage's |size|()))
(aImg's addRepresentation:thisImage)
(aPDFdoc's insertPage:(PDFPage's alloc()'s initWithImage:aImg) atIndex:pageNum)
set pageNum to pageNum + 1
end repeat
return (aPDFdoc's writeToFile:bb) as boolean
end convertMultiPageTiffToPDF
on changeExtensionInPath(extStr as string, aPath as string)
set pathString to NSString's stringWithString:aPath
set theExtension to pathString's pathExtension()
set thePathNoExt to pathString's stringByDeletingPathExtension()
set newPath to thePathNoExt's stringByAppendingPathExtension:extStr
return newPath as string
end changeExtensionInPath

How Can I Show Progress/Countdown to Next Action In The Menubar Systemwide Applescript

I created an Applescript that every 600 seconds retrieve the last line of a log file and add it to a Google Sheet spreadsheet.
This is extremely useful, but it is starting to annoy me not knowing when the next action will be performed.
So now I'm trying to display the progress (or countdown in seconds) to the next action in the menubar, so I can, kind of, be aware that the focus application will change.
Can please someone point me in the right direction?
--- Added Information ---
Now, instead of showing a countdown, I want to just simply show how many steps left, and it's still not working. This is a test code I'm working on:
set progress total steps to 12
set progress completed steps to 0
set progress description to "Running..."
set progress additional description to "ETA: 120 Seconds"
repeat with a from 1 to 12
delay 10
set progress completed steps to a
set ETA to a * 10
set progress additional description to "ETA: " & ETA & " seconds"
end repeat
What I'm doing wrong?
Based on the link red_menace gave in comments and the screenshot you provided, here's a script that (I think) will give the results you want. It's not an automator workflow. This is an AppleScript stay-open application. Copy it into Script Editor and save is as an application: choose "Application" from the File Format pulldown menu on the save screen, and make sure you check the Stay open after run handler checkbox. then run the application like normal and see the demo.
use framework "AppKit"
use framework "Foundation"
use scripting additions
property ca : current application
property NSStatusBar : class "NSStatusBar"
property NSMenu : class "NSMenu"
property NSMenuItem : class "NSMenuItem"
property NSImage : class "NSImage"
property NSProgressIndicator : class "NSProgressIndicator"
property NSView : class "NSView"
property NSTextField : class "NSTextField"
property idle_time : 1
global status_bar_item, progress_views, idx
on run
set progress_views to {}
set status_bar_item to NSStatusBar's systemStatusBar's statusItemWithLength:(ca's NSSquareStatusItemLength)
set status_bar_item's |menu| to NSMenu's alloc's initWithTitle:""
set status_bar_item's |menu|'s minimumWidth to 220
my setImage(ca's NSImageNameSmartBadgeTemplate)
my addToStatusMenu(my progress_view_obj("Number 1"))
my addToStatusMenu(my progress_view_obj("Number 2"))
set idx to 0
end run
on idle
set idx to idx + 1
repeat with this_obj in progress_views
set rand_numb to (random number from 1 to 9)
(this_obj's progress_indicator's incrementBy:rand_numb)
this_obj's changeLabel("Adding: " & rand_numb)
end repeat
if idx > 20 then
quit
end if
return idle_time
end idle
on quit
-- remove status item and quit
NSStatusBar's systemStatusBar's removeStatusItem:status_bar_item
continue quit
end quit
on addToStatusMenu(obj)
set statusMenu to status_bar_item's |menu|
statusMenu's addItem:(obj's menu_item)
set end of progress_views to obj
end addToStatusMenu
on progress_view_obj(label_value)
script prog_view_obj
-- text field
property progress_indicator : missing value
property menu_item : missing value
property label_field : missing value
global content_view
-- make label field
set label_field to NSTextField's labelWithString:label_value
set label_field's translatesAutoresizingMaskIntoConstraints to false
-- progress indicator
set progress_indicator to NSProgressIndicator's alloc's initWithFrame:(ca's NSMakeRect(0, 0, 200, 20))
set progress_indicator's indeterminate to false
progress_indicator's setStyle:(ca's NSProgressIndicatorStyleBar)
progress_indicator's startAnimation:me
set progress_indicator's translatesAutoresizingMaskIntoConstraints to false
-- content view for menu item
set content_view to NSView's alloc's initWithFrame:(ca's NSMakeRect(0, 0, 200, 100))
set content_view's translatesAutoresizingMaskIntoConstraints to false
content_view's addSubview:label_field
content_view's addSubview:progress_indicator
-- constraints to arrange elements
--set view_height_constraint to content_view's heightAnchor's constraintEqualToConstant:100
--view_height_constraint's setActive:true
set lf_left_margin to content_view's leadingAnchor's constraintEqualToAnchor:(label_field's leadingAnchor) |constant|:-10
lf_left_margin's setActive:true
set pi_left_margin to content_view's leadingAnchor's constraintEqualToAnchor:(progress_indicator's leadingAnchor) |constant|:-10
pi_left_margin's setActive:true
set pi_right_margin to content_view's trailingAnchor's constraintEqualToAnchor:(progress_indicator's trailingAnchor) |constant|:10
pi_left_margin's setActive:true
set top_spacing_const to content_view's topAnchor's constraintEqualToAnchor:(label_field's topAnchor) |constant|:-10
set mid_spacing_const to label_field's bottomAnchor's constraintEqualToAnchor:(progress_indicator's topAnchor) |constant|:-10
set bott_spacing_const to content_view's bottomAnchor's constraintGreaterThanOrEqualToAnchor:(progress_indicator's bottomAnchor) |constant|:10
top_spacing_const's setActive:true
mid_spacing_const's setActive:true
bott_spacing_const's setActive:true
content_view's updateConstraints()
-- create and flesh out menu item
set menu_item to NSMenuItem's alloc's init()
set menu_item's view to content_view
content_view's updateConstraints()
on changeLabel(label_value)
set label_field's stringValue to label_value
end changeLabel
on changeMinValue(val)
set progress_indicator's minValue to val
end changeMinValue
on changeMaxValue(val)
set progress_indicator's maxValue to val
end changeMaxValue
on changeValue(val)
set progress_indicator's doubleValue to val
end changeValue
on currentValue()
return progress_indicator's doubleValue() as integer
end currentValue
end script
run prog_view_obj
return prog_view_obj
end progress_view_obj
on setImage(imageName)
status_bar_item's button's setImageScaling:(ca's NSImageScaleProportionallyDown)
status_bar_item's button's setImage:(NSImage's imageNamed:imageName)
status_bar_item's button's setImagePosition:(ca's NSImageLeft)
end setImage
You shouldn't need to change anything except in the run and idle handlers — the first to set up the menus and the second to increment the progress bars or update the labels as needed. You can change how frequently the indicators update by increasing or decreasing the idle-time property (it's currently set to run the idle loop once a second). You'll only need to get into the big, messy handler if you need to change the layout or size of the menu items.
Technical point: I've put each progress view inside a script object (script prog_view_obj) to make it easier to work with. That may take some time for you to wrap your head around — it's tricky AppleScript — but at any rate, there's a bunch of convenience handlers at the end of the script object definition that you may find useful.

Applescript - ghosted result with applescript set file label

I did make this script in automator.
property unset : 0
property orange : 1
property red : 2
property yellow : 3
property blue : 4
property purple : 5
property green : 6
property grey : 7
property tmplFileName : "__ReadMe" as string
property fileType : ".txt" as string
property labelTag : red
on run {input, parameters}
tell application "Finder"
set currentPath to insertion location as text
-- set filePath to POSIX path of currentPath
set txtfilename to tmplFileName & fileType
set txtFile to make new file at insertion location as alias with properties {name:txtfilename}
set the label index of the item (txtFile as alias) to my labelTag
select txtFile
open txtFile
end tell
return input
end run
It give's me the following result. A ghosted or visible only disabled file.
What do I wrong? This happens only when I set the label. Its about this line
set the label index of the item (txtFile as alias) to my labelTag
Any suggestions? Thank you.
Still don't understand why the file is disabled. Anyway and moving forward, after some reading I came with this as a test script, and it works. Need some error management like check existing file.
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
property |NSURL| : a reference to current application's NSURL
property tmplFileName : "__ReadMe" as string
property fileType : ".txt" as string
property labelTag : "red"
-- Replace tags;
-- setTags - pass a list with new tags and replacing any existing
-- forPath - POSIX path
on setTags:tagList forPath:POSIXPath
set aURL to current application's |NSURL|'s fileURLWithPath:POSIXPath
aURL's setResourceValue:tagList forKey:(current application's NSURLTagNamesKey) |error|:(missing value)
end setTags:forPath:
on run {input, parameters}
tell application "Finder"
set txtfilename to tmplFileName & fileType
set txtFile to make new file at insertion location as alias with properties {name:txtfilename}
set POSIXPath to POSIX path of (txtFile as text)
(my setTags:{labelTag} forPath:POSIXPath)
select txtFile
tell application "TextEdit"
activate
open txtFile as alias
end tell
end tell
return input
end run
Hope this help some other people as well. Do I get now a plus one vote back from above. As a side note, can some one explain why I did get a -1? just curious.
Thank you.
I took a stab in the dark and thought maybe the problem was the size of the file that was created, was 0 kb's. I decided to add a handler with the write to file command and added a single space as a character to the file. This made the file size 1 byte and then setting the label index worked. I made a few minor adjustments to your initial code, for my purposes but here are the changes I've made and my version of the code.
local unset, orange, red, yellow, blue, purple, green, grey
set {unset, orange, red, yellow, blue, purple, green, grey} to {0, 1, 2, 3, 4, 5, 6, 7}
set tmplFileName to "__ReadMe"
set nameExtension to ".txt"
set labelTag to red
tell application "Finder"
set currentPath to insertion location
set txtfilename to tmplFileName & nameExtension
set txtFile to make new file at insertion location as alias with properties {name:txtfilename, name extension:nameExtension}
my writeToTheFile(txtFile as alias)
set the label index of (txtFile as alias) to labelTag
open txtFile
end tell
on writeToTheFile(txtFile as alias)
set theFile to txtFile as alias
set theText to " "
try
set writeToFile to open for access theFile with write permission
write theText to writeToFile as text starting at eof
close access theFile
on error errMsg number errNum
try
close access theFile
end try
end try
end writeToTheFile

Set value of an AXDateTimeArea

I want to set the value of an AXDateTimeArea GUI element via Applescript. Attached is a screenshot of the Accessibility Inspector showing the element.
This is the code that I tried. No errors are thrown, but the value of the element doesn't change.
set value of attribute "AXValue" of tElement to "2012-06-21 13:45:18 +0000"
Additionally I tried the following lines but no success nor an error thrown.
set value of tElement to "2012-06-21 13:45:18 +0000"
set value of tElement to (current date)
set value of attribute "AXValue" of tElement to (current date)
This is always within a loop over the content of the sheet/window:
tell application "System Events"
tell process "myprocess"
set tElements to entire contents of (get sheet 1 of window 1)
repeat with tElement in tElements
end repeat
end tell
end tell
This is a screenshot:

Resources