Page 1 of 1

Change the app's icon in real-time

Posted: Mon Oct 09, 2023 2:37 pm
by Torf
Hello.

Please, is it possible to change the icon of my app in real-time?

I supose that Cocoa would to have a method for do this, but I can not find it.

Thanks you in advance!

Re: Change the app's icon in real-time

Posted: Mon Oct 09, 2023 3:37 pm
by yuki
The applicationIconImage property of NSApplication does what you want, e.g.:

Code: Select all

; Get application instance.
Define app = CocoaMessage(#Null, #Null, "NSApplication sharedApplication")
; Create a solid black image.
Define img = CreateImage(#PB_Any, 256, 256, 32)
; Replace the application's icon with our image.
CocoaMessage(#Null, app, "setApplicationIconImage:", ImageID(img))
Here's a complete, runnable example which should create an empty window and update the app's icon on a timer:

Code: Select all

EnableExplicit

Define wnd = OpenWindow(#PB_Any, 0, 0, 400, 300, "Dynamic Icon", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Define app = CocoaMessage(#Null, #Null, "NSApplication sharedApplication")
Define img = CreateImage(#PB_Any, 256, 256, 32)
Define iconSizeStep = 0

AddWindowTimer(wnd, 1, 32)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow, #PB_Event_Menu
      Break
    Case #PB_Event_Timer
      iconSizeStep % 100
      iconSizeStep + 1
      StartDrawing(ImageOutput(img))
        DrawingMode(#PB_2DDrawing_AllChannels)
        Box(0, 0, OutputWidth(), OutputHeight(), $00000000)
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        Circle(OutputWidth() / 2, OutputHeight() / 2, (iconSizeStep / 200.0) * OutputWidth(), $ffff00ff)
      StopDrawing()
      CocoaMessage(#Null, app, "setApplicationIconImage:", ImageID(img))
  EndSelect
ForEver

Re: Change the app's icon in real-time

Posted: Mon Oct 09, 2023 7:42 pm
by deseven
That's a very clever example, yuki!
I didn't even know that icon changing could be so fast, you could even create animations that way :)

Re: Change the app's icon in real-time

Posted: Mon Oct 09, 2023 10:25 pm
by yuki
deseven wrote: Mon Oct 09, 2023 7:42 pm That's a very clever example, yuki!
I didn't even know that icon changing could be so fast, you could even create animations that way :)
Yeah, it can be changed quite rapidly!

Though, submitting many images in short succession this way (esp. large ones) can ramp up load a bit. So, while it's definitely usable for very dynamic but brief transitions, continuous long-running animations may have users complain (about either visual noise or fan noise :wink:).

You can take control of the application's NSDockTile presentation to carefully optimise this, but it will come at the cost of added code complexity.

Re: Change the app's icon in real-time

Posted: Thu Oct 12, 2023 8:32 am
by Torf
yuki wrote: Mon Oct 09, 2023 3:37 pm The applicationIconImage property of NSApplication does what you want, e.g.:

Code: Select all

; Get application instance.
Define app = CocoaMessage(#Null, #Null, "NSApplication sharedApplication")
; Create a solid black image.
Define img = CreateImage(#PB_Any, 256, 256, 32)
; Replace the application's icon with our image.
CocoaMessage(#Null, app, "setApplicationIconImage:", ImageID(img))
Here's a complete, runnable example which should create an empty window and update the app's icon on a timer:

Code: Select all

EnableExplicit

Define wnd = OpenWindow(#PB_Any, 0, 0, 400, 300, "Dynamic Icon", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
Define app = CocoaMessage(#Null, #Null, "NSApplication sharedApplication")
Define img = CreateImage(#PB_Any, 256, 256, 32)
Define iconSizeStep = 0

AddWindowTimer(wnd, 1, 32)
Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow, #PB_Event_Menu
      Break
    Case #PB_Event_Timer
      iconSizeStep % 100
      iconSizeStep + 1
      StartDrawing(ImageOutput(img))
        DrawingMode(#PB_2DDrawing_AllChannels)
        Box(0, 0, OutputWidth(), OutputHeight(), $00000000)
        DrawingMode(#PB_2DDrawing_AlphaBlend)
        Circle(OutputWidth() / 2, OutputHeight() / 2, (iconSizeStep / 200.0) * OutputWidth(), $ffff00ff)
      StopDrawing()
      CocoaMessage(#Null, app, "setApplicationIconImage:", ImageID(img))
  EndSelect
ForEver

Thanks very much, Yuki, it's just I need. It's a very good example.