How to change the selection color of a ListViewGadget()?

Mac OSX specific forum
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

How to change the selection color of a ListViewGadget()?

Post by Wolfram »

How can I change the color of the selected item of a ListViewGadget()?
The default color is alway blue.

I found this example, but I'm unable to translate it.
https://stackoverflow.com/questions/946 ... stableview
macOS Catalina 10.15.7
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by mk-soft »

Its like from Shardik...

Update v0.4
- Pack code

Code: Select all

EnableExplicit

ImportC ""
  class_addMethod(Class.I, Selector.I, *Callback, Types.P-ASCII)
  sel_registerName(MethodName.P-ASCII)
EndImport

; ---------------------------------------------------------------------------------------

Procedure AddGadgetCallback(Gadget, MethodName.s, *Callback, TypeParams.s)
  Protected AppDelegate = CocoaMessage(0, CocoaMessage(0, 0, "NSApplication sharedApplication"), "delegate")
  Protected DelegateClass = CocoaMessage(0, AppDelegate, "class")
  Protected Selector = sel_registerName(MethodName)
  Protected Class = class_addMethod(DelegateClass, Selector, *Callback, TypeParams)
  Protected Result = CocoaMessage(0, GadgetID(Gadget), "setDelegate:", AppDelegate)
  ProcedureReturn Class
EndProcedure

; ---------------------------------------------------------------------------------------

Procedure NSColor(Color)
  Protected Alpha.CGFloat, Blue.CGFloat, Green.CGFloat, Red.CGFloat
  Alpha = 1
  Red = Red(Color) / 255
  Green = Green(Color) / 255
  Blue = Blue(Color) / 255
  ProcedureReturn CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@", 
               @Red, "green:@", @Green, "blue:@", @Blue, "alpha:@", @Alpha)
EndProcedure

; ---------------------------------------------------------------------------------------

Global SelectedTextColor
Global SelectedBackcolor

ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I, *Column, Row.I)
  Protected Selected
  
  Selected = CocoaMessage(0, TableView, "selectedRow")
  
  If Selected <> Row
    CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0, "NSColor textColor"))
  Else
    CocoaMessage(0, Cell, "setDrawsBackground:", #YES)
    CocoaMessage(0, Cell, "setTextColor:", NSColor(SelectedTextColor))
    CocoaMessage(0, Cell, "setBackgroundColor:", NSColor(SelectedBackColor))
  EndIf
  
EndProcedure

; ---------------------------------------------------------------------------------------

OpenWindow(0, 200, 100, 430, 100, "Disable highlight and selection color example")

ListViewGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20)
;ListIconGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20, "Name", 110)

;AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")

CocoaMessage(0, GadgetID(0), "setSelectionHighlightStyle:", -1); ** don't highlight selection **

AddGadgetCallback(0, "tableView:willDisplayCell:forTableColumn:row:", @CellDisplayCallback(), "v@:@@@@") 

SelectedTextColor = #Black
SelectedBackColor = $25C1FF

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      Break
    Case #PB_Event_Gadget
      If EventGadget() = 0
        If EventType() = #PB_EventType_Change
        EndIf
      EndIf
  EndSelect
ForEver
Last edited by mk-soft on Sat Jan 19, 2019 1:18 pm, edited 1 time in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to change the selection color of a ListViewGadget()?

Post by Wolfram »

Thanks, but this is not the same.
In your example is a white line around the selection and on the right side a big one.
In the code (see link) they use a rectangle. Are you able to translate this code?

Image
Image
macOS Catalina 10.15.7
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to change the selection color of a ListViewGadget()?

Post by wilbert »

The example you are mentioning assumes a view based NSTableView.
As far as I understand, PB still uses a cell based one; don't know if it is possible to do it this way.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by mk-soft »

I also noticed that my code is trash,
because the callback is global for all gadgets with NSTableView...
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by Shardik »

wilbert wrote:The example you are mentioning assumes a view based NSTableView.
As far as I understand, PB still uses a cell based one; don't know if it is possible to do it this way.
That's correct. And yes, it's possible to modify the drawing of the selected cell's background color in a cell-based NSTableView.
mk-soft wrote:I also noticed that my code is trash,
because the callback is global for all gadgets with NSTableView...
Your code is fine but in order to fulfill Wolfram's requirements you have to enlarge the cell frame area for drawing the background. Have you tried your code with 2 ListIconGadgets? Their selection highlight color is different (one changed and the other default)! You can control this with setting the delegate for each ListIconGadget for which you want to change the selection highlight color.

I have tested my example successfully on these MacOS versions:
- 10.6.8 'Snow Leopard' with PB 5.62 x86
- 10.7.5 'Lion' with PB 5.62 x86
- 10.8.5 'Mountain Lion' with PB 5.62 x86
- 10.10.5 'Yosemite' with PB 5.62 x86
- 10.13.6 'High Sierra' with PB 5.70 x64

Unfortunately on MacOS 10.9.5 'Mavericks' colored areas in front of and below the ListIconGadget are displayed:
Image
I have experienced these graphics bugs also in other similar NSTableView examples. Perhaps this is a bug in Mavericks because in Yosemite and later these graphics bugs don't appear anymore. The transition from cell-based NSTableViews to view-based ones were implemented in the version upgrade from Snow Leopard to Lion.

Code: Select all

EnableExplicit

#SelectedTextColor = #Black
#SelectedBackColor = $FFFF00

Define AppDelegate = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass = CocoaMessage(0, AppDelegate, "class")
Define Selector.I = sel_registerName_("tableView:willDisplayCell:" +
  "forTableColumn:row:")

Procedure NSColor(Color)
  Protected Alpha.CGFloat = 1
  Protected Blue.CGFloat = Blue(Color) / 255
  Protected Green.CGFloat = Green(Color) / 255
  Protected Red.CGFloat = Red(Color) / 255

  ProcedureReturn CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@",
    @Red, "green:@", @Green, "blue:@", @Blue, "alpha:@", @Alpha)
EndProcedure

ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I, *Column, Row.I)
  Protected CellFrame.NSRect
  Protected SelectedRow.I

  SelectedRow = CocoaMessage(0, TableView, "selectedRow")
 
  If SelectedRow <> Row
    CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0,
      "NSColor textColor"))
  Else
    CocoaMessage(0, Cell, "setTextColor:", NSColor(#SelectedTextColor))
    CocoaMessage(@CellFrame, TableView,
      "frameOfCellAtColumn:", 0,
      "row:", Row)

    ; ----- Enlarge cell frame

    CellFrame\origin\x - 1
    CellFrame\origin\y - 1
    CellFrame\size\height + 2

    If OSVersion() <= #PB_OS_MacOSX_10_7
      CellFrame\size\width + 3
    Else
      CellFrame\size\width + 8
    EndIf

    ; ----- Draw cell background
    
    CocoaMessage(0, NSColor(#SelectedBackColor), "setFill")
    CocoaMessage(0, 0, "NSBezierPath fillRect:@", @CellFrame)
  EndIf
EndProcedure

OpenWindow(0, 200, 100, 300, 100, "Modified selection color")
ListViewGadget(0, 10, 10, WindowWidth(0) - 20, WindowHeight(0) - 20)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ +
  "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ +
  "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ +
  "321 Logo Drive, Mouse House, Downtown")
SetActiveGadget(0)

; ----- Initialize callback
class_addMethod_(DelegateClass, Selector, @CellDisplayCallback(), "v@:@@@@")
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)

; ----- Disable default highlighting
CocoaMessage(0, GadgetID(0), "setSelectionHighlightStyle:", -1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by mk-soft »

@Shardik

Ok, it's just one callback for all the gadgets that want to use the function.
Added a map where the colors are stored.
Except for that it has been extended to change the background color for all Columns.
But the text color doesn't work yet.

Update 2
- Bugfix ListIconGadget

Code: Select all

EnableExplicit

Structure udtSelectionColor
  Type.i
  TextColor.i
  BackColor.i
EndStructure

Global NewMap SelectionColor.udtSelectionColor()

Procedure SetSelectionColor(Gadget, TextColor, BackColor)
  Protected Key.s = Hex(GadgetID(Gadget))
  SelectionColor(Key)\Type = GadgetType(Gadget)
  SelectionColor(Key)\TextColor = TextColor
  SelectionColor(Key)\BackColor = BackColor
EndProcedure

Define AppDelegate = CocoaMessage(0, CocoaMessage(0, 0,
  "NSApplication sharedApplication"), "delegate")
Define DelegateClass = CocoaMessage(0, AppDelegate, "class")
Define Selector.I = sel_registerName_("tableView:willDisplayCell:" +
  "forTableColumn:row:")

Procedure NSColor(Color)
  Protected Alpha.CGFloat = 1
  Protected Blue.CGFloat = Blue(Color) / 255
  Protected Green.CGFloat = Green(Color) / 255
  Protected Red.CGFloat = Red(Color) / 255

  ProcedureReturn CocoaMessage(0, 0, "NSColor colorWithDeviceRed:@",
    @Red, "green:@", @Green, "blue:@", @Blue, "alpha:@", @Alpha)
EndProcedure

ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I, *Column, Row.I)
  Protected CellFrame.NSRect
  Protected Column.I
  Protected SelectedRow.I
 
  If Not FindMapElement(SelectionColor(), Hex(TableView))
    ProcedureReturn 0
  EndIf
 
  SelectedRow = CocoaMessage(0, TableView, "selectedRow")
 
  If SelectedRow <> Row
    CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0,
      "NSColor textColor"))
  Else
    If SelectionColor()\Type = #PB_GadgetType_ListIcon
      ;Column = Val(PeekS(CocoaMessage(0, CocoaMessage(0, *Column, "identifier"),
      ;                                "UTF8String"), -1, #PB_UTF8))
      Column = CocoaMessage(0, CocoaMessage(0, TableView, "tableColumns"), "indexOfObject:", *Column)
    EndIf

    CocoaMessage(0, Cell,
      "setTextColor:", NSColor(SelectionColor()\TextColor))
    CocoaMessage(@CellFrame, TableView,
      "frameOfCellAtColumn:", Column,
      "row:", Row)
     
    ; ----- Enlarge cell frame
    CellFrame\origin\x - 1
    CellFrame\origin\y - 1
    CellFrame\size\height + 2
 
    If OSVersion() <= #PB_OS_MacOSX_10_7
      CellFrame\size\width + 3
    Else
      CellFrame\size\width + 8
    EndIf

    ; ----- Draw cell background
    CocoaMessage(0, NSColor(SelectionColor()\BackColor), "setFill")
    CocoaMessage(0, 0, "NSBezierPath fillRect:@", @CellFrame)
  EndIf
EndProcedure

OpenWindow(0, 200, 100, 480, 240, "Disable highlight and selection color example")

ListIconGadget(0, 10, 10, WindowWidth(0) - 20, 100, "Name", 110)

AddGadgetColumn(0, 1, "Address", GadgetWidth(0) - GetGadgetItemAttribute(0, 0, #PB_ListIcon_ColumnWidth) - 8)
AddGadgetItem(0, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(0, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(0, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")

ListViewGadget(1, 10, 120, WindowWidth(0) - 20, 100)
AddGadgetItem(1, -1, "Harry Rannit" + #LF$ + "12 Parliament Way, Battle Street, By the Bay")
AddGadgetItem(1, -1, "Ginger Brokeit" + #LF$ + "130 PureBasic Road, BigTown, CodeCity")
AddGadgetItem(1, -1, "Didi Foundit" + #LF$ + "321 Logo Drive, Mouse House, Downtown")

; ----- Initialize callback
class_addMethod_(DelegateClass, Selector, @CellDisplayCallback(), "v@:@@@@")

; ----- Set delagate
CocoaMessage(0, GadgetID(0), "setDelegate:", AppDelegate)
SetSelectionColor(0, #Black, #Red)

CocoaMessage(0, GadgetID(1), "setDelegate:", AppDelegate)
SetSelectionColor(1, #Gray, #Green)

; ----- Disable default highlighting
CocoaMessage(0, GadgetID(0), "setSelectionHighlightStyle:", -1)
CocoaMessage(0, GadgetID(1), "setSelectionHighlightStyle:", -1)

Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
Last edited by mk-soft on Sun Jan 20, 2019 7:06 pm, edited 2 times in total.
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
Shardik
Addict
Addict
Posts: 1989
Joined: Thu Apr 21, 2005 2:38 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by Shardik »

mk-soft wrote:But the text color doesn't work yet.
Your loop over the different columns is incorrect und unnecessary because the cell in each column is called automatically. Just try my modified callback which I tested successfully on Snow Leopard with PB 5.62 x86:

Code: Select all

ProcedureC CellDisplayCallback(Object.I, Selector.I, TableView.I, Cell.I, *Column, Row.I)
  Protected CellFrame.NSRect
  Protected Column.I
  Protected SelectedRow.I
 
  If Not FindMapElement(SelectionColor(), Hex(TableView))
    ProcedureReturn 0
  EndIf
 
  SelectedRow = CocoaMessage(0, TableView, "selectedRow")
 
  If SelectedRow <> Row
    CocoaMessage(0, Cell, "setDrawsBackground:", #NO)
    CocoaMessage(0, Cell, "setTextColor:", CocoaMessage(0, 0,
      "NSColor textColor"))
  Else
    If TableView = GadgetID(0)
      Column = Val(PeekS(CocoaMessage(0, CocoaMessage(0, *Column, "identifier"),
        "UTF8String"), -1, #PB_UTF8))
    EndIf

    CocoaMessage(0, Cell,
      "setTextColor:", NSColor(SelectionColor()\TextColor))
    CocoaMessage(@CellFrame, TableView,
      "frameOfCellAtColumn:", Column,
      "row:", Row)
     
    ; ----- Enlarge cell frame
    CellFrame\origin\x - 1
    CellFrame\origin\y - 1
    CellFrame\size\height + 2
 
    If OSVersion() <= #PB_OS_MacOSX_10_7
      CellFrame\size\width + 3
    Else
      CellFrame\size\width + 8
    EndIf

    ; ----- Draw cell background
    CocoaMessage(0, NSColor(SelectionColor()\BackColor), "setFill")
    CocoaMessage(0, 0, "NSBezierPath fillRect:@", @CellFrame)
  EndIf
EndProcedure
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by mk-soft »

Ok :D

Have update my last code.
Now is save the gadget type inside the map of the selection colors...

Edit
Now i have create a module for table view colors

Link: viewtopic.php?f=19&t=72124
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3870
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: How to change the selection color of a ListViewGadget()?

Post by wilbert »

You can also get the column index like this

Code: Select all

Column = CocoaMessage(0, CocoaMessage(0, TableView, "tableColumns"), "indexOfObject:", *Column)
Might be a bit faster compared to the Val / PeekS method.
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: How to change the selection color of a ListViewGadget()?

Post by mk-soft »

@wilbert
Thanks, its work fine
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
Wolfram
Enthusiast
Enthusiast
Posts: 567
Joined: Thu May 30, 2013 4:39 pm

Re: How to change the selection color of a ListViewGadget()?

Post by Wolfram »

Thank you all. ...It works as it should. ;-)
macOS Catalina 10.15.7
Post Reply