script AEXAppDelegate
property parent : class "NSObject"
property theItem : {} -- the main property; array controller binds its content array to this
-- IBOutlets
property |window| : missing value
property theArrayController : missing value
property selectedPKGPath : missing value
property defaults : missing value
property testValue : missing value
property certsAdded : 0
property certsValue : missing value
property selectedRow : missing value
property selectedObjects : missing value
property NSColor : class "NSColor" of current application
property theColor : missing value
property selectedPKGsColour : missing value
property thePath : missing value
property runNumber : 0
property additionalPKGs : missing value
on applicationWillFinishLaunching:aNotification
set my selectedPKGsColour to current application's NSColor's blackColor()
log selectedPKGsColour
-- populate plist file with defaults (will not overwrite non-default settings))
regDefaults_(me)
-- retrieve plist values
retrieveDefaults_(me)
set my theItem to {thePath:additionalPKGs, theColor:selectedPKGsColour}
log theItem
end applicationWillFinishLaunching:
on regDefaults_(sender)
tell current application's NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to registerDefaults_({additionalPKGs:additionalPKGs}) as list
end regDefaults_
-- Get values from plist
on retrieveDefaults_(sender)
tell defaults to set my additionalPKGs to objectForKey_("additionalPKGs") as list
end retrieveDefaults_
on selectPKG_(sender)
try
set runNumber to runNumber + 1
choose file of type {"com.apple.installer-package-archive"} with prompt "Select a .pkg to add:" default location (path to desktop folder)
set my selectedPKGPath to POSIX path of result
tell theArrayController to addObject:selectedPKGPath
tell defaults to registerDefaults_({additionalPKGs:additionalPKGs}) as list
set my theItem to theItem & {thePath:additionalPKGs, theColor:selectedPKGsColour}
log theItem
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(additionalPKGs, "additionalPKGs")
end tell
end try
if runNumber is greater than 1
set my selectedPKGsColour to current application's NSColor's redColor()
log selectedPKGsColour
end if
end selectPKG_
on deletePKG_(sender)
tell theArrayController to set my selectedObjects to selectedObjects()
log selectedObjects
tell theArrayController to removeObjects:selectedObjects
log "done"
log additionalPKGs
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(additionalPKGs, "additionalPKGs")
end tell
log "updated plist"
end deletePKG_
on testButton_(sender)
repeat with theItem in additionalPKGs
try
-- Check for file
do shell script "ls " & quoted form of theItem
log "Found " & theItem
on error
log theItem & " is missing"
display dialog "Cannot Find: " & additionalPKGs & ". Do you wish to proceed?" with icon 2 buttons {"No", "Yes"}
-- Set missing items text to red.
set my selectedPKGsColour to current application's NSColor's redColor()
end try
end repeat
end testButton_
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
end script
I changed the array controllers content array bindings to a “Content Array For Mulitple Selection” which allows the app to compile.
In the bindings for “packages” column, i have the value bound to the array controller. The “Controller Key” is arrangedObjects & the “Model Key Path” is thePath.
I get the below in the apps logs, but nothing in the TableView.
If additionalPKGs is a list of paths, you need to loop through and make it a list of records. You’re just making a single record, with the color as one value, and the list of paths as the other.
Your problem is that you’re not building your array/list of records/dictionaries properly. Think of it as an AppleScript problem, not an ASObjC problem.
Yes. When you read additionalPKGs, it’s presumably just a list of paths. What you want is a list/array of records/dictionaries, so you make one (off the top of my head):
set theBlack to current application's NSColor's blackColor()
set theList to {}
repeat with aValue in (additionalPKGs as list)
set end of theList to {thePath:aValue, theColor:theBlack}
end repeat
set my theItem to current application's NSMutableArray's arrayWithArray:theList
You don’t say how you’re going to trigger the change of color. If you’re checking that the files in the paths exists, you’d do that in the above repeat list, and use the red color if the item is missing.
It’s working, but not sure if there is a “better” way to read the arrays value & update the plist rather that the slight sledgehammer approach i’ve taken.
There are 3 other issues:
How can I stop the array from having duplicate entries? << last “real” issue.
How do I change the text for a certain row? (targeted by index, currently i delete the old object & re-add) << minor issue, could be resolved with the below.
How can you keep the array in alphabetical order? sortedArrayUsingSelector:“localizedStandardCompare:” didn’t seem to work & I guess that is as we’re using an NSMutableArray.
script AEXAppDelegate
property parent : class "NSObject"
property theItem : {} -- the main property; array controller binds its content array to this
-- IBOutlets
property |window| : missing value
property theArrayController : missing value
property selectedPKGPath : missing value
property defaults : missing value
property aValue : missing value
property selectedObjects : missing value
property NSColor : class "NSColor" of current application
property selectedPKGsColour : missing value
property additionalPKGs : missing value
property theList: {}
property plistValue : {}
property pkgsMissing : false
on applicationWillFinishLaunching:aNotification
-- populate plist file with defaults (will not overwrite non-default settings))
regDefaults_(me)
-- retrieve plist values
retrieveDefaults_(me)
set selectedPKGsColour to current application's NSColor's blackColor()
repeat with aValue in (additionalPKGs as list)
set end of theList to {thePath:aValue, theColor:selectedPKGsColour}
end repeat
set my theItem to current application's NSMutableArray's arrayWithArray:theList
end applicationWillFinishLaunching:
on regDefaults_(sender)
tell current application's NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to registerDefaults_({additionalPKGs:additionalPKGs}) as list
end regDefaults_
-- Get values from plist
on retrieveDefaults_(sender)
tell defaults to set my additionalPKGs to objectForKey_("additionalPKGs") as list
end retrieveDefaults_
on selectPKG_(sender)
set selectedPKGsColour to current application's NSColor's blackColor()
try
choose file of type {"com.apple.installer-package-archive"} with prompt "Select a .pkg to add:" default location (path to desktop folder)
set my selectedPKGPath to POSIX path of result
set theList to {thePath:selectedPKGPath, theColor:selectedPKGsColour}
tell theArrayController to addObject:theList
set plistValue to additionalPKGs as list
set end of plistValue to selectedPKGPath
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(plistValue, "additionalPKGs")
end tell
end try
end selectPKG_
on deletePKG_(sender)
tell theArrayController to set my selectedObjects to selectedObjects()
tell theArrayController to removeObjects:selectedObjects
set plistValue to (theItem's valueForKey:"thePath") as list
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(plistValue, "additionalPKGs")
end tell
end deletePKG_
on testButton_(sender)
repeat with selectedPKGPath in additionalPKGs
try
-- Check for file
do shell script "ls " & quoted form of selectedPKGPath
log "Found " & selectedPKGPath
on error
log selectedPKGPath & " is missing"
set theList to {theColor:selectedPKGsColour, thePath:selectedPKGPath}
tell theArrayController to removeObject:theList
set my selectedPKGsColour to current application's NSColor's redColor()
set theList to {thePath:selectedPKGPath, theColor:selectedPKGsColour}
tell theArrayController to addObject:theList
set pkgsMissing to true
end try
end repeat
if pkgsMissing is true then
display dialog "Cannot find one or more .pkgs. Do you wish to proceed?" with icon 2 buttons {"No", "Yes"}
end if
end testButton_
you’re trying to sort a dictionary, which is not sortable.
Again, to display multiple rows in a table view the datasource must be an Array of Dictionaries in terms of ObjC. Each array contains the data for one table row
on applicationWillFinishLaunching_(aNotification)
regDefaults_(me)
retrieveDefaults_(me)
set selectedPKGsColour to current application's NSColor's blackColor()
repeat with aValue in additionalPKGs
theArrayController's addObject:{thePath:aValue, theColor:selectedPKGsColour}
end repeat
end applicationWillFinishLaunching_
The dictionary’s are added to the array controller directly.
As theItem “ I recommend to rename it to something more descriptive like pkgList “ is bound to the array controller the value is updated automatically
on applicationWillFinishLaunching:aNotification
tell current application's NSUserDefaults to set defaults to standardUserDefaults()
-- populate plist file with defaults (will not overwrite non-default settings))
regDefaults_(me)
-- retrieve plist values
set additionalPKGs to retrieveDefaults_(me)
set selectedPKGsColour to current application's NSColor's blackColor()
repeat with aValue in additionalPKGs
(arrayController's addObject:{thePath:aValue, theColor:selectedPKGsColour})
end repeat
end applicationWillFinishLaunching:
on regDefaults:sender
tell defaults to registerDefaults:{additionalPKGs:{}}
end regDefaults:
-- Get values from plist
on retrieveDefaults:sender
tell defaults to return objectForKey_("additionalPKGs")
end retrieveDefaults:
on selectPKG:sender
set selectedPKGsColour to current application's NSColor's blackColor()
try
choose file of type {"com.apple.installer-package-archive"} with prompt "Select a .pkg to add:" default location (path to desktop folder)
set my selectedPKGPath to POSIX path of result
set newPKG to {thePath:selectedPKGPath, theColor:selectedPKGsColour}
tell theArrayController to addObject:newPKG
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(theitems's valueForKey:"thePath", "additionalPKGs") -- valueForKey creates a list of all "thePath" values
end tell
on error e
display dialog e
end try
end selectPKG:
Gents, thank you so much. I finally have something working as I want. This is a POC that will be added to my app (https://github.com/macmule/AutoCasperNBI) in the next commit.
Below is the code, process is below… Mostly it’s over 3 sections:
Read in values from a plist.
Check that the pkgs in the plist exist, if they do not change text colour to red.
Populate array post check, with the text in black if pkg exists… red if not.
Allow users to add pkgs.
Stop users from adding duplicate pkgs.
Update array in app & plist.
Allow users to select & delete pkgs.
Update array in app & plist.
In the app i’ll add handling for if the array in the plist is empty.
As to sorting the Array, i was being to precious about it. Why script it when the header can sort… allowing the user to select.
One bit to add to the app would be a rescan button, that would be bound to checkAdditionalPKGs, this would allow someone to connect an external drive that holds the PKGs & then re-check that the files exist without restarting the app.
script AEXAppDelegate
property parent : class "NSObject"
property theItem : {} -- the main property; array controller binds its content array to this
-- IBOutlets
property |window| : missing value
property theArrayController : missing value
property selectedPKGPath : missing value
property defaults : missing value
property selectedObjects : missing value
property NSColor : class "NSColor" of current application
property selectedPKGsColour : missing value
property additionalPKGs : ""
property theList: {}
property plistValue : {}
property pkgsMissing : false
----- ON START -----
on applicationWillFinishLaunching:aNotification
-- populate plist file with defaults (will not overwrite non-default settings))
regDefaults_(me)
-- retrieve plist values
retrieveDefaults_(me)
-- Check additional pkgs array, & amend accordingly
checkAdditionalPKGs_(me)
end applicationWillFinishLaunching:
on regDefaults_(sender)
tell current application's NSUserDefaults to set defaults to standardUserDefaults()
tell defaults to registerDefaults_({additionalPKGs:additionalPKGs}) as list
end regDefaults_
-- Get values from plist
on retrieveDefaults_(sender)
tell defaults to set my additionalPKGs to objectForKey_("additionalPKGs") as list
end retrieveDefaults_
----- THE MAIN PARTS -----
-- Check additional pkgs array, & amend accordingly
on checkAdditionalPKGs_(sender)
repeat with selectedPKGPath in additionalPKGs
try
-- Check for file
do shell script "ls " & quoted form of selectedPKGPath
set selectedPKGsColour to current application's NSColor's blackColor()
(theArrayController's addObject:{thePath:selectedPKGPath, theColor:selectedPKGsColour})
on error
log selectedPKGPath & " is missing"
set theList to {theColor:selectedPKGsColour, thePath:selectedPKGPath}
tell theArrayController to removeObject:theList
set my selectedPKGsColour to current application's NSColor's redColor()
(theArrayController's addObject:{thePath:selectedPKGPath, theColor:selectedPKGsColour})
set pkgsMissing to true
end try
end repeat
if pkgsMissing is true then
--Logic to be added after sender to AutoCasperNBI if build button pressed.
end if
end checkAdditionalPKGs_
-- Add PKG selected by user
on selectPKG_(sender)
set selectedPKGsColour to current application's NSColor's blackColor()
try
choose file of type {"com.apple.installer-package-archive"} with prompt "Select a .pkg to add:" default location (path to desktop folder)
set my selectedPKGPath to POSIX path of result
-- Do not add if a duplicate
if (additionalPKGs does not contain selectedPKGPath) then
set plistValue to additionalPKGs as list
if plistValue is equal to missing value then
set plistValue to selectedPKGPath
else
set end of plistValue to selectedPKGPath
end if
(theArrayController's addObject:{thePath:selectedPKGPath, theColor:selectedPKGsColour})
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(plistValue, "additionalPKGs")
end tell
else
log "Duplicate selected"
end if
end try
end selectPKG_
-- Remove Selected PKG
on deletePKG_(sender)
tell theArrayController to set my selectedObjects to selectedObjects()
tell theArrayController to removeObjects:selectedObjects
set plistValue to (theItem's valueForKey:"thePath") as list
tell standardUserDefaults() of current application's NSUserDefaults
setObject_forKey_(plistValue, "additionalPKGs")
end tell
end deletePKG_
-- On Terminate
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
end script
Again, thank you both so much.
This site, your input & Shane book & site have been massively helpful. Not just for this project, but over the years too.