Getting Cocoa system colors...

Mac OSX specific forum
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Getting Cocoa system colors...

Post by kenmo »

I am new to using CocoaMessage() and the Objective-C style functions... I am also new to OSX's API...

My goal is to get the Mac's system colors in PB's RGB format, starting for example with "windowBackgroundColor".

This is what I've come up with so far, and I've tried many things, but Line 6 (the last CocoaMessage) gives me an error that the object is nil, and I always get a result of $000000. (I know the first NSColor is being created, but I guess I am using the ColorSpace wrong?)

Code: Select all

Procedure.i GetCocoaColor(ColorName.s)
  Protected NSColor.i = CocoaMessage(#Null, #Null, "NSColor " + ColorName)
  If (NSColor)
    Protected.CGFloat R, G, B, A
    NSColor = CocoaMessage(#Null, NSColor, "colorUsingColorSpaceName:$", @"deviceRGBColorSpace")
    CocoaMessage(#Null, NSColor, "getRed:@", @R, "green:@", @G, "blue:@", @B, "alpha:@", @A)
    ProcedureReturn (RGB(Int(R*255), Int(G*255), Int(B*255)))
  Else
    ProcedureReturn (-1)
  EndIf
EndProcedure

Debug Hex(GetCocoaColor("windowBackgroundColor"))
Delay(1000)
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Getting Cocoa system colors...

Post by wilbert »

This explains the problem
http://stackoverflow.com/questions/2687 ... colorspace

What might work for you is to use the color to draw onto an image and get the pixel color.

Code: Select all

Procedure.i GetCocoaColor(ColorName.s)
  Protected.i Result, Rect.NSRect, Image, NSColor = CocoaMessage(#Null, #Null, "NSColor " + ColorName)
  If NSColor
    Rect\size\width = 1
    Rect\size\height = 1
    Image = CreateImage(#PB_Any, 1, 1)
    StartDrawing(ImageOutput(Image))
    CocoaMessage(#Null, NSColor, "drawSwatchInRect:@", @Rect)
    Result = Point(0, 0)
    StopDrawing()
    FreeImage(Image)
    ProcedureReturn Result
  Else
    ProcedureReturn -1
  EndIf
EndProcedure

Debug Hex(GetCocoaColor("windowBackgroundColor"))
Delay(1000)
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Danilo
Addict
Addict
Posts: 3037
Joined: Sat Apr 26, 2003 8:26 am
Location: Planet Earth

Re: Getting Cocoa system colors...

Post by Danilo »

I think "windowBackgroundColor" does not work because it is a pattern, not a simple, single color.

What about this to get some other system colors?

Code: Select all

Procedure.q GetCocoaColor(ColorName.s)
    Protected.CGFloat R, G, B, A
    NSColor = CocoaMessage(#Null, #Null, "NSColor colorWithCatalogName:$",@"System","colorName:$",@ColorName)
    If NSColor
        ;Debug NSColor
        
        NSColor = CocoaMessage(#Null, NSColor, "colorUsingColorSpaceName:$",@"NSCalibratedRGBColorSpace")
        If NSColor
            ;Debug NSColor
            
            CocoaMessage(@R.CGFloat, NSColor,"redComponent")
            CocoaMessage(@G.CGFloat, NSColor,"greenComponent")
            CocoaMessage(@B.CGFloat, NSColor,"blueComponent")
            CocoaMessage(@A.CGFloat, NSColor,"alphaComponent")
            
            ProcedureReturn (RGBA(Int(R*255), Int(G*255), Int(B*255), Int(A*255)) & $FFFFFFFF)
        EndIf
    EndIf
    ProcedureReturn (-1)
EndProcedure

Macro ShowColor(colorName)
    ShowColor_col.q = GetCocoaColor(colorName)
    If ShowColor_col = -1
        Debug Str(-1) + " ("+colorName+")"
    Else
        Debug "Color: " + Hex(ShowColor_col) + " ("+colorName+")"
    EndIf
EndMacro



ShowColor("windowBackgroundColor")                  ; PATTERN -> Returns a pattern color that will draw the ruled lines for the window background.

ShowColor("windowFrameColor")                       ; Returns the system color used for window frames, except for their text.
ShowColor("windowFrameTextColor")                   ; Returns the system color used for the text in window frames.

ShowColor("alternateSelectedControlColor")          ; Returns the system color used for the face of a selected control.
ShowColor("alternateSelectedControlTextColor")      ; Returns the system color used for text in a selected control.

;ShowColor("controlAlternatingRowBackgroundColors")  ; ARRAY -> Returns an array containing the system specified background colors for alternating rows in tables and lists.

ShowColor("gridColor")                              ; Returns the system color used for the optional gridlines in, for example, a table view.
ShowColor("headerColor")                            ; Returns the system color used as the background color for header cells in table views and outline views.
ShowColor("headerTextColor")                        ; Returns the system color used for text in header cells in table views and outline views.

ShowColor("highlightColor")                         ; Returns the system color that represents the virtual light source on the screen.

ShowColor("keyboardFocusIndicatorColor")            ; Returns the system color that represents the keyboard focus ring around controls.
ShowColor("knobColor")                              ; Returns the system color used for the flat surface of a slider knob that hasn’t been selected.
ShowColor("selectedKnobColor")                      ; Returns the system color used for the slider knob when it is selected.

ShowColor("scrollBarColor")                         ; Returns the system color used for scroll “bars”—that is, for the groove in which a scroller’s knob moves

ShowColor("selectedMenuItemColor")                  ; Returns the system color used for the face of selected menu items.
ShowColor("selectedMenuItemTextColor")              ; Returns the system color used for the text in menu items.

ShowColor("selectedTextBackgroundColor")            ; Returns the system color used for the background of selected text.
ShowColor("selectedTextColor")                      ; Returns the system color used for selected text.

ShowColor("shadowColor")                            ; Returns the system color that represents the virtual shadows cast by raised objects on the screen.

ShowColor("textColor")                              ; Returns the system color used for text.
ShowColor("textBackgroundColor")                    ; Returns the system color used for the text background.

ShowColor("secondarySelectedControlColor")          ; Returns the system color used in non-key views.
ShowColor("selectedControlColor")                   ; Returns the system color used for the face of a selected control.
ShowColor("selectedControlTextColor")               ; Returns the system color used for text in a selected control—a control being clicked or dragged.


ShowColor("controlBackgroundColor")                 ; Returns the system color used for the background of large controls.
ShowColor("controlColor")                           ; Returns the system color used for the flat surfaces of a control.
ShowColor("controlDarkShadowColor")                 ; Returns the system color used for the dark edge of the shadow dropped from controls.
ShowColor("controlHighlightColor")                  ; Returns the system color used for the highlighted bezels of controls.
ShowColor("controlLightHighlightColor")             ; Returns the system color used for light highlights in controls.
ShowColor("controlShadowColor")                     ; Returns the system color used for the shadows dropped from controls.
ShowColor("controlTextColor")                       ; Returns the system color used for text on controls that aren’t disabled.
ShowColor("disabledControlTextColor")               ; Returns the system color used for text on disabled controls.


ShowColor("clearColor")                             ; Returns an NSColor object whose grayscale and alpha values are both 0.0.


ShowColor("whiteColor")                             ; color names
ShowColor("blackColor")
ShowColor("blueColor")
ShowColor("greenColor")
ShowColor("brownColor")
ShowColor("cyanColor")
ShowColor("grayColor")
ShowColor("lightGrayColor")
ShowColor("darkGrayColor")
ShowColor("magentaColor")
ShowColor("orangeColor")
ShowColor("purpleColor")
ShowColor("redColor")
ShowColor("yellowColor")

My output:

Code: Select all

-1 (windowBackgroundColor)
Color: FF999999 (windowFrameColor)
Color: FF000000 (windowFrameTextColor)
Color: FFCD5D2B (alternateSelectedControlColor)
Color: FFFFFFFF (alternateSelectedControlTextColor)
Color: FFC0C0C0 (gridColor)
Color: FF999999 (headerColor)
Color: FF000000 (headerTextColor)
Color: FFFEFFFE (highlightColor)
Color: FFD0894B (keyboardFocusIndicatorColor)
Color: FFAC8586 (knobColor)
Color: FF865052 (selectedKnobColor)
Color: FF999999 (scrollBarColor)
Color: FFF25B2C (selectedMenuItemColor)
Color: FFFEFFFE (selectedMenuItemTextColor)
Color: FFFECAA6 (selectedTextBackgroundColor)
Color: FF000000 (selectedTextColor)
Color: FF000000 (shadowColor)
Color: FF000000 (textColor)
Color: FFFEFFFE (textBackgroundColor)
Color: FFCACACA (secondarySelectedControlColor)
Color: FFFECAA6 (selectedControlColor)
Color: FF000000 (selectedControlTextColor)
Color: FFFEFFFE (controlBackgroundColor)
-1 (controlColor)
Color: FF000000 (controlDarkShadowColor)
Color: FFE2E2E2 (controlHighlightColor)
Color: FFFEFFFE (controlLightHighlightColor)
Color: FF8D8D8D (controlShadowColor)
Color: FF000000 (controlTextColor)
Color: FF6C6C6C (disabledControlTextColor)
Color: 0 (clearColor)
Color: FFFFFFFF (whiteColor)
Color: FF000000 (blackColor)
Color: FFFF0000 (blueColor)
Color: FF00FF00 (greenColor)
Color: FF336699 (brownColor)
Color: FFFFFF00 (cyanColor)
Color: FF7F7F7F (grayColor)
Color: FFAAAAAA (lightGrayColor)
Color: FF555555 (darkGrayColor)
Color: FFFF00FF (magentaColor)
Color: FF007FFF (orangeColor)
Color: FF7F007F (purpleColor)
Color: FF0000FF (redColor)
Color: FF00FFFF (yellowColor)
controlColor and windowBackgroundColor return -1 here, other system colors work.
User avatar
kenmo
Addict
Addict
Posts: 1967
Joined: Tue Dec 23, 2003 3:54 am

Re: Getting Cocoa system colors...

Post by kenmo »

Thanks to both of you. I am learning the mysterious Cocoa ways...

My specific condition is: I'm trying to get two OS colors, for drawing to CanvasGadgets. #1 is the color of an empty PB window, and #2 is the color inside an empty PanelGadget. On my system these seem to be $EDEDED and $E5E5E5 (slightly different grays).

@wilbert - Your example works, it gives me the correct window color. Is there a way to get the PanelGadget inner color?

@Danilo - Your example is cleaner, and thanks for the list of color names, but none of them seem to represent the two colors I mentioned above! Must be part of the windowBackgroundColor pattern? Also this Apple page says the colors with "control" in their names are no longer meaningful: http://developer.apple.com/library/Mac/ ... d/20000790

I guess I am spoiled by Windows, there I can get both colors with two simple calls to GetSysColor_() :(
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: Getting Cocoa system colors...

Post by wilbert »

If you only want to draw boxes, you can use the Cocoa drawing methods.
This gives you a list of named colors

Code: Select all

If OpenWindow(0, 0, 0, 322, 150, "Color list", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  EditorGadget(0, 8, 8, 306, 133)
  
  Lists = CocoaMessage(0, 0, "NSColorList availableColorLists")
  NumLists = CocoaMessage(0, Lists, "count")
  For l = 1 To NumLists
    ColorList = CocoaMessage(0, Lists, "objectAtIndex:", l - 1)
    ColorListName.s = PeekS(CocoaMessage(0, CocoaMessage(0, ColorList, "name"), "UTF8String"), -1, #PB_UTF8)
    Keys = CocoaMessage(0, ColorList, "allKeys")
    NumKeys = CocoaMessage(0, Keys, "count")
    For k = 1 To NumKeys
      Key = CocoaMessage(0, Keys, "objectAtIndex:", k - 1)
      KeyName.s = PeekS(CocoaMessage(0, Key, "UTF8String"), -1, #PB_UTF8)
      AddGadgetItem(0, -1, ColorListName + " -> " + KeyName)
    Next
  Next
  
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
An example to use them

Code: Select all

Procedure ColorBox(x, y, Width, Height, ColorName.s, ListName.s = "System")
  Protected Rect.NSRect, Color.i, ColorList.i = CocoaMessage(0, 0, "NSColorList colorListNamed:$", @ListName)
  If ColorList
    Color = CocoaMessage(0, ColorList, "colorWithKey:$", @ColorName)
    If Color
      Rect\origin\x = x
      Rect\origin\y = OutputHeight() - Height - y
      Rect\size\width = Width
      Rect\size\height = Height
      CocoaMessage(0, Color, "setFill")
      CocoaMessage(0, 0, "NSBezierPath fillRect:@", @Rect)
    EndIf
  EndIf
EndProcedure



If OpenWindow(0, 0, 0, 200, 200, "CanvasGadget", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
  CanvasGadget(0, 0, 0, 200, 200)
  
  If StartDrawing(CanvasOutput(0))
    ColorBox(0, 0, 200, 200, "controlColor")
    ColorBox(10, 10, 180, 180, "controlHighlightColor")
    ColorBox(20, 20, 20, 20, "Green", "Apple")
    ColorBox(20, 60, 20, 20, "Aqua", "Crayons")
    StopDrawing()
  EndIf
  
  Repeat
    Event = WaitWindowEvent()
  Until Event = #PB_Event_CloseWindow
EndIf
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Getting Cocoa system colors...

Post by Keya »

I just tried Danilo's color enumeration test as I was interested to see where the default window background color is stored (seemingly not 'windowBackgroundColor' which returns -1 as previously observed), interestingly not one of the values it returned is the default window background color on my straight-out-of-the-box El Capitan (i checked with Photoshop's Color Picker to see it's RGB $ECECEC, which is also the same value wilbert's Point(0, 0) workaround successfully returns)
Post Reply