TheOnlyOneHere
TheOnlyOneHere

Reputation: 123

How to show composite icons using Display Dialog

Is there any way to display Display Dialog icons like macOS does, I tried looking for the icon below in /System/Library/CoreServices/CoreTypes.bundle but I didn't find it.

enter image description here

set myIcon to (path to resource "myIcon.icns")
display dialog "this is my icon" buttons {"OK"} default button "OK" with icon myIcon

Upvotes: 0

Views: 281

Answers (2)

Ted Wrigley
Ted Wrigley

Reputation: 3184

All of the standard Apple icons are stored here:

`/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources`

You can access them directly, as in the following.

set iconFIle to choose file "Choose an icon file" of type {"com.apple.icns"} ¬
    default location POSIX file "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources"
display dialog "This is a test" with icon iconFIle

Note that the Finder sometimes does composite icons by using one icon as an overlay or badge applied to another icon. For instance, I believe the image you posted above is the file "KEXT.icns" overlaid with the file "AlertCautionBadgeIcon.icns." You can mimic that behavior with the following script.

set basePath to POSIX path of (path to library folder from system domain) & "CoreServices/CoreTypes.bundle/Contents/Resources/"
set tempStoragePath to POSIX path of (path to temporary items from user domain)

-- set the name of the main idon, and the overlay icon
set mainName to "KEXT"
set overlayName to "AlertCautionBadgeIcon"

set kextImgPath to basePath & mainName & ".icns"
set alertImgPath to basePath & overlayName & ".icns"
set tempSetPath to quoted form of (tempStoragePath & mainName & ".iconset" as text)
set tempOverlayPath to quoted form of (tempStoragePath & overlayName & ".iconset" as text)

-- decompose the icns into iconsets, so that we can do the overlays by hand
do shell script "iconutil -c iconset -o " & tempSetPath & " " & kextImgPath
do shell script "iconutil -c iconset -o " & tempOverlayPath & " " & alertImgPath

tell application "System Events"
    set mainFolder to folder (mainName & ".iconset") of folder tempStoragePath
    set overlayFolder to folder (overlayName & ".iconset") of folder tempStoragePath
    set theFiles to (files of mainFolder whose name extension is "png")

    (*
      iconsets are folders with files named (e.g.) 'icon_16x16.png', '[email protected]'
      this loop runs through and finds matching sized elements of the set, then sends
      them to the script object's handler for processing with ASOC
    *)
    repeat with thisFile in theFiles
        set fileName to name of thisFile
        if exists file (name of thisFile) of overlayFolder then
            asocBits's mungePNGs(POSIX path of thisFile, POSIX path of (file fileName of overlayFolder))
        end if
    end repeat
end tell

-- convert the iconset folders back to icns files, then send the file to display dialog
do shell script "iconutil -c icns " & tempSetPath
display dialog "This is a test" with icon POSIX file (tempStoragePath & mainName & ".icns")

script asocBits
    use framework "Foundation"
    use framework "AppKit"

    property NSImage : class "NSImage"
    property NSBitmapImageRep : class "NSBitmapImageRep"

    on mungePNGs(mainImg, overlay)
        -- get respective images
        set mainImgObj to NSImage's alloc's initWithContentsOfFile:mainImg
        set overlayObj to NSImage's alloc's initWithContentsOfFile:overlay

        -- create a destination image
        set newImage to NSImage's alloc's initWithSize:(mainImgObj's |size|)
        newImage's lockFocus()

        -- set up apprpriate drawing rects, then draw the two images into the new image.
        set newRect to current application's CGRectZero as list
        set imgSize to mainImgObj's |size| as list
        set item 2 of newRect to item 1 of imgSize

        set h to (height of item 1 of imgSize)

        (* 
          these were trial and error. remember that (0,0) is the bottom left,
          not the top left (y goes from bottom to top).
          placementRect is supposed to be where the overlay is placed.
          cropRect is the part of the overlay that's pasted.
          different badges have their effective images in different quadrants.
        *)
        set placementRect to current application's CGRectMake(0.5 * h, 0.0, h, h)
        set cropRect to current application's CGRectMake(0.5 * h, 0.5 * h, h, h)

        mainImgObj's drawInRect:newRect

        set op to current application's NSCompositeSourceOver
        overlayObj's drawInRect:placementRect fromRect:cropRect operation:op fraction:1.0

        -- create a bitmap representation and save it back to the main iconset file
        set bitmapRep to NSBitmapImageRep's alloc's initWithFocusedViewRect:newRect
        newImage's unlockFocus()

        set PNGType to current application's NSBitmapImageFileTypePNG
        set imgData to (bitmapRep's representationUsingType:PNGType |properties|:(missing value))

        imgData's writeToFile:mainImg atomically:false
    end mungePNGs
end script

The script is on the slow side, but it gets the job done. In the long run, it might be more efficient simply to use the script object to create icns files that you can store in the bundle and call at need.

Technical detail: I've used a script object to isolate the ASOC routines from the rest of the script. ASOC and osax commands don't always play well together. In this case, display dialog with icon always seems to throw an error if any frameworks have been invoked. I suppose I could have used tell framework "..." blocks instead, but the script object appealed to me...

Upvotes: 1

vadian
vadian

Reputation: 285082

As Ted correctly answered you can't display compound icons.

But you can do the opposite, displaying your application icon with a caution or stop badge. To do so omit the reference to the icon and use the other – enumerated – with icon parameter

display dialog "this is my icon" buttons {"OK"} default button "OK" with icon caution

display dialog "this is my icon" buttons {"OK"} default button "OK" with icon stop

Upvotes: 1

Related Questions