To change a single cell’s color, I have the following:
I know it is probably not the BEST way to go about it, but I do the following. When i get to a line in my code that i change a cell AND i want to call attention to it, i set the following:
set ChangeTheColorOfMailingLogCells to 1
set ChangeTheColorForOrderID to "999-999-999"
set the contents of data cell "table_status" of myRow to trackinginfo
here is the will change cell handler:
on will display cell theObject cell theCell row theRow table column tableColumn
if ChangeTheColorOfMailingLogCells is equal to 1 then
if the name of theObject is equal to "mailinglog_table" then
if the identifier of tableColumn is equal to "table_status" then
set EndiciaDetailDataSource to the data source of theObject
set rowcounter to 1
repeat with i in every data row of EndiciaDetailDataSource
if rowcounter is equal to theRow then
if contents of data cell "table_ordernumber" of i is equal to ChangeTheColorForOrderID then
log "Would highlight row # " & rowcounter & " or " & theRow & " having the email: " & contents of data cell "table_customeremail" of i
set text color of theCell to {30000, 0, 0}
set ChangeTheColorOfMailingLogCells to 0
set ChangeTheColorForOrderID to ""
-- works without the following
-- update theObject
exit repeat
end if
end if
set rowcounter to rowcounter + 1
end repeat
end if
end if
end if
end will display cell
Okay, what happens is the following:
If the row to change is the 3rd row, then the 3rd through the last rows (that column only) turn red. IF I SCROLL the table view or in any way cause it to update (by resizeing or such) then the ENTIRE column for all the rows (even the first through the second) update to red.
Have you actually been able to get either text or the data cell to have a specified color? It seems to be one of the great secrets of applescript. I’ve found all kinds of people asking the question but have never found an answer.
many thanks for this - I didn’t know this is possible from AppleScript (I always used to subclass NSTableColumn for this + override ‘dataCellForRow:’). ‘on will display cell’ is a much easier solution
here an example to set text and background colors in a table view (single column with an NSTextFieldCell, ‘Draw background’ option checked):
global ds
on awake from nib theObject
set content of theObject to {"red background", "green text", "blue text", "red text", "green background", "blue background", "nothing", "blue text", "red background"}
set ds to data source of theObject
end awake from nib
on will display cell theObject cell theCell row theRow table column tableColumn
set cellcontents to (contents of data cell 1 of data row theRow of ds)
if cellcontents contains "text" then
set textCol to (my getColor(cellcontents))
if textCol is not {} then
set text color of theCell to textCol
set background color of theCell to {65535, 65535, 65535}
end if
else if cellcontents contains "background" then
set bCol to (my getColor(cellcontents))
if bCol is not {} then
set background color of theCell to bCol
set text color of theCell to {65535, 65535, 65535}
end if
else
set text color of theCell to {0, 0, 0}
set background color of theCell to {65535, 65535, 65535}
end if
end will display cell
on getColor(cellcontents)
if cellcontents contains "red" then
return {65535, 0, 0}
else if cellcontents contains "green" then
return {0, 65535, 0}
else if cellcontents contains "blue" then
return {0, 0, 65535}
else
return {}
end if
end getColor
OK, this is great. But It does slow down operation quite a bit if you have a routine to check the contents for validity and color accordingly.
In fact, for some reason, when I double click in a cell in order to edit, the entire column turns the color of the last text colored cell. As does the cell itself if I just select it. Any ideas what might be going on?
what’s going on? The problem with this method of colorizing the table is, that you really have to tell every cell of the colored column which colors you want - If you don’t, they’ll get the colors of the last colors specified for this column’s cell … Why? That’s because there isn’t a permanently existing cell object for every row of a column - the column creates them ‘on the fly’ - using instances of a ‘master cell’. The only chance to influence this process is the applescript handler - as described here - or an Objective-C method (subclass overriding ‘dataCellForRow:’). Both methods are called by the column whenever it is about to display a cell. The column says: ‘Hey - I want to display the cell object of row n’ and here is your chance to say - ‘Ok - take it, but change it’s textcolor or background color etc.’
If the Applescript way is too slow it’s since your script part that determines the colors has to be called everytime the column updates (which can be quite often).
So what remains might be the NSTableColumn subclass. I’ve rewritten my example of two msgs above using this method. The big advantage is speed - the subclass holds a list (NSMutableArray) for every row’s colors so if there are changes the applescript is only called once to determine the colors of a cell.
The subclass files:
go to Interface Builder → MainMenu.nib → Classes Tab and Subclass ‘NSTableColumn’ (Ctrl+Click it and select the first menu item of the context menu)
name this Subclass -(‘ColoredCellsTableColumn’ in my example)
select the new Subclass and Controll-Click it - then select ‘Create Files for …’
select the column you want to use the subclass for and select the ‘Custom Class’ Tab of the Inspector Window (or enter Apple+5)
choose the new Subclass for the column
save
then switch to Xcode
there should be 2 new files added to your project: .h and.m
and here’s the AppleScript. I’ve added two buttons to demonstrate how to insert & delete.
The table column is named: table column “coloredCells” of table view “tv” of scroll view “sv” of window “main”
The buttons: button “insert” of window “main” and button “delete” of window “main”
global ds
on awake from nib theObject
set theStartContent to {"1 red background", "2 green text", "3 blue text", "4 red text", "5 green background", "6 blue background", "7 nothing", "8 blue text", "9 red background"}
set theRow to 1
set theColumn to table column "coloredCells" of table view "tv" of scroll view "sv" of window "main"
call method "initColors" of theColumn
repeat with nextObj in theStartContent
my setColors(nextObj, theRow, theColumn)
set theRow to theRow + 1
end repeat
set content of theObject to theStartContent
set ds to data source of theObject
end awake from nib
on cell value changed theObject row theRow table column tableColumn value theValue
my setColors(theValue, theRow, tableColumn)
end cell value changed
on clicked theObject
if (name of theObject) is "delete" then
tell table view "tv" of scroll view "sv" of window "main"
set sel to selected rows
repeat with n from (count of sel) to 1 by -1
delete data row (item n of sel) in it's data source
call method "deleteRow:" of table column "coloredCells" with parameter (item n of sel)
end repeat
set selected rows to {}
end tell
else if (name of theObject) is "insert" then
tell table view "tv" of scroll view "sv" of window "main"
tell it's data source
set newItem to "new item with " & (some item of {"red", "green", "blue"}) & (some item of {" text", " background"})
set insertBefore to (random number (count of data rows)) + 1
make new data row at before data row insertBefore
set contents of data row insertBefore to newItem
end tell
call method "insertRow:" of table column "coloredCells" with parameter insertBefore
my setColors(newItem, insertBefore, table column "coloredCells")
end tell
end if
end clicked
on setColors(cellcontents, theRow, theColumn)
tell theColumn
if cellcontents contains "text" then
set textCol to (my getColor(cellcontents))
if textCol is not {} then
call method "setTextColor:forRow:" of it with parameters {textCol, theRow}
call method "setColor:forRow:" of it with parameters {{65535, 65535, 65535}, theRow}
end if
else if cellcontents contains "background" then
set bCol to (my getColor(cellcontents))
if bCol is not {} then
call method "setColor:forRow:" of it with parameters {bCol, theRow}
call method "setTextColor:forRow:" of it with parameters {{65535, 65535, 65535}, theRow}
end if
else
call method "setTextColor:forRow:" of it with parameters {{0, 0, 0}, theRow}
call method "setColor:forRow:" of it with parameters {{65535, 65535, 65535}, theRow}
end if
end tell
end setColors
on getColor(cellcontents)
if cellcontents contains "red" then
return {65535, 0, 0}
else if cellcontents contains "green" then
return {0, 65535, 0}
else if cellcontents contains "blue" then
return {0, 0, 65535}
else
return {}
end if
end getColor
just to change the text color of the selected cell(s) try this
on will display cell theObject cell theCell row theRow table column tableColumn
if theCell is highlighted then
set text color of theCell to {0, 0, 0}
end if
end will display cell
as far as I remember you have to connect the event handler of the table view in Interface Builder