I want to change the text color of every individual cell of a table view depending of its value,
but I don’t know how to get an access to such a cell (if it’s possible at all).
Here is my unsuccessfully attempt:
set theTableColumns to theTableView's tableColumns() as list
set theColumn to item 12 of theTableColumns -- column for interest
set theCount to theDataSource's |count|()
repeat with aRow from 1 to theCount
set theDataCell to theColumn's dataCellForRow_(aRow) -- ??
set theItemList to (item aRow of theDataSource)
if (theItemList's valueForKey_("theValue")) is in {"a", "b", "c", "d"} then
beep -- it beeps
theDataCell's setTextColor_(class "NSColor"'s redColor) -- no result
else
theDataCell's setTextColor_(class "NSColor"'s greenColor)
end if
end repeat
It’s the same problem: the color is changed for the whole column and not for the single cell because all cells have the same id.
set acell to theColumn's dataCellForRow_(aRow)
... send to:
on tableView_willDisplayCell_forTableColumn_row_(aTableView, acell, aColumn, aRow)
log aTableView -- ok
log acell -- result: <NSTextFieldCell: 0x142ab40> -- for all cells
log aColumn -- ok
log aRow -- ok
acell's setTextColor_(current application's class "NSColor"'s greenColor) -- each cell in the column becomes green
end tableView_willDisplayCell_forTableColumn_row_
So I did it, similarly as in my first post. The following handler shows why it can’t work (in my opinion).
on tableView_willDisplayCell_forTableColumn_row_(aTableView, acell, aColumn, aRow)
if aTableView is myTableView then
set columnIdent to aColumn's identifier
if columnIdent as string is equal to "myColumnForInterest" then -- restriction
set theTableViewRecord to {aRow, acell}
log theTableViewRecord
end if
end if
end tableView_willDisplayCell_forTableColumn_row_
The result is, for every row I got the same cell’s id. That colors the complete column same.
Imagine that the handler works like an old TV display.
When the setNeedsDisplay: method of the table view is called (by reloadData or automatically by a NSArrayController)
each cell is drawn one after another. So the willDisplayCell handler will be called as much as how many cells are there.
The handler provides column (aColumn) and row (aRow) information to be able to identify the cell.
This gives you the capability to manipulate every cell before it’s drawn.
This is an ObjC example which I use to display the disk S.M.A.R.T status in a table view column.
It considers green color for OK and read color for failure and also center alignment and inverse color in case of the row is currently selected
Here is now the result. Because I don’t need to set style and text, the handler is reduced.
on tableView_willDisplayCell_forTableColumn_row_(aTableView, acell, aColumn, aRow)
if aTableView is myTableView then
if (aColumn's identifier)'s isEqualToString_("theIdentifier") then
set isSelected to (myTableView's selectedRowIndexes)'s containsIndex_(aRow)
set cellContent to acell's stringValue()
if cellContent is in {"a", "b", "c"} then
set aColor to current application's class "NSColor"'s greenColor
else if cellContent is in {"d"} then
set aColor to current application's class "NSColor"'s orangeColor
else
set aColor to current application's class "NSColor"'s redColor
end if
if isSelected then
set txtColor to current application's class "NSColor"'s whiteColor
else
set txtColor to aColor
end if
acell's setTextColor_(txtColor)
end if
end if
end tableView_willDisplayCell_forTableColumn_row_
I was wondering of all of this could be accomplished using bindings only?
Thanks to this post http://macscripter.net/viewtopic.php?id=34282 I have the most part of it working without AppleScript code, except for the conditional part.
Is there a way to make formatting of color conditional via bindings?
I’m using an ArrayControler, all works fine except for the conditional stuff, for which I hav no clue where to look.
So far I thought I tried all the obvious, to me that is…
Let’s say I try to set the text color of the selected row.
I have a row that holds the NSColor
in IB I made a binding in the Table Column Bindings’ Text Color part to it’s own Array Controller
Controller Key: selectedObjects → I figured this would return true if the row is selected
Model Key Path: the key of the column holding the NSColor
If I use ‘selection’ as the Controller Key for the binding, it is actually using my NSColor, except for the conditional part I hoped to accomplish. If I click a row, every row get’s the color of the clicked row’s NSColor. This might make sense since I used the binding of the Table Column in stead of the Text Field Cell.
If remove the binding from the Table Column and apply it on the Text Field Cell’s Text Color, it kind of works, the wrong way though…
Let’s say I click the second row, which holds colorRed in it’s NSColor, nothing happens, if I then click row three, which holds colorGreen, it turns red. It turns out this way the invoked row’s color has only influence on the next clicked row.
Anyway, I guess I overlooked the fact that I can’t restore the original text color when a row get’s ‘unclicked’, via bindings.
Right, but sometimes the delegate way is the only one.
For example you can’t bind the title of a button cell in table view,
actually you can, but the result is weird. The only way to accomplish this is the same delegate method
The posted handler works without any bindings to an additional array controller. It works only with the delegate method! That means:
Set the table view as a property (here: property MyTableView: missing value) ; Save!
Open the HUD-Window of the table view.
a) Bind it’s name in the Referencing Outlets to the AppDelegate’s cube (or File’s Owner cube in a document based app)
b) Bind the ‘delegate’ in the Outlets to the AppDelegate’s cube (or File’s Owner cube in a document based app.
That’s all of bindings.
Put the on tableView_willDisplayCell_forTableColumn_row_(aTableView, acell, aColumn, aRow) - handler somewhere in your script. The ‘system’ will call repetitive the information of the table view.
Try something like this:
on tableView_willDisplayCell_forTableColumn_row_(aTableView, acell, aColumn, aRow)
log aTableView
log acell
log aColumn
log aRow
end tableView_willDisplayCell_forTableColumn_row_
Setting the text color on selection, as mentioned by Heiner and Stefan, works great.
Now for the looks I’d like to use “Source List” Highlighting for my table view in IB.
Guess what, text coloring stops working if you don’t use black as the standard text color.
FYI, passing a NSMutableAttributedString to the table’s arrayController in stead of just a AS string seems to solve the aforementioned color displaying problem while using “Source List” Highlighting for my table view.