Set a specific cell in a field to a different color
Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller
Set a specific cell in a field to a different color
Is this possible? I messed around with htmltext but it doesn't fill the entire cell.
-
- VIP Livecode Opensource Backer
- Posts: 977
- Joined: Sat Apr 08, 2006 7:47 am
- Contact:
Re: Set a specific cell in a field to a different color
Not with the built-in field, I'm afraid. You may be interested in RunRevPlanet's Flexible Grid for LiveCode as an alternative to using a table text field.
Jan Schenkel.
Jan Schenkel.
Quartam Reports & PDF Library for LiveCode
www.quartam.com
www.quartam.com
Re: Set a specific cell in a field to a different color
Paul,
this works only for cells that have text in them. I don't know if something like this is what you are looking after.
regards
Bernd
Code: Select all
on mouseUp
set the itemdelimiter to tab
set the backgroundcolor of item 2 of line 1 of field "myTableField" to red
end mouseUp
regards
Bernd
Re: Set a specific cell in a field to a different color
I was looking for more to fill the entire cell rather than just a small box around the text. Setting the background color of the item works just like setting <bgcolor> with htmltext. I suppose it will have to do! Thanks again for the help 

Re: Set a specific cell in a field to a different color
Hi Paul,
In the absence of a tidy way to colour a single cell in a standard table field, I might mention one approach I played with a while ago. It involved three “layers”. I first created a simple, blank field whose backgroundColor was white, which I called field “White Backdrop”. On top of this I placed a table field with its opaque property set to false, i.e. you could see its cell divider lines, but it was otherwise transparent, so you saw the backdrop field behind it. Then I created small, borderless cell-sized fields, and gave them the backgroundColor I wanted. I placed them over the cells I wanted coloured, then using the property inspector, size and position, set their layers so they were visible between the white backdrop and the table field. Individual cells, whole or partial rows or columns could be coloured in this way. To make a large table field scrollable, I grouped everything- backdrop, colour fields, and table field, into a single group which had horizontal and vertical scroll bars. Thus when you scrolled, you scrolled the group- everything moved together, i.e. the colour fields “stayed with” the cells they provided a colour background for. Originally, the colour fields were sized and positioned individually by hand, but I seem to recall some potential for doing this with some somewhat obscure scripting if need be. I hope this account is not too confusing- it's a bit "ham fisted" and it may or may not have use for your particular requirements.
Regards,
Michael
In the absence of a tidy way to colour a single cell in a standard table field, I might mention one approach I played with a while ago. It involved three “layers”. I first created a simple, blank field whose backgroundColor was white, which I called field “White Backdrop”. On top of this I placed a table field with its opaque property set to false, i.e. you could see its cell divider lines, but it was otherwise transparent, so you saw the backdrop field behind it. Then I created small, borderless cell-sized fields, and gave them the backgroundColor I wanted. I placed them over the cells I wanted coloured, then using the property inspector, size and position, set their layers so they were visible between the white backdrop and the table field. Individual cells, whole or partial rows or columns could be coloured in this way. To make a large table field scrollable, I grouped everything- backdrop, colour fields, and table field, into a single group which had horizontal and vertical scroll bars. Thus when you scrolled, you scrolled the group- everything moved together, i.e. the colour fields “stayed with” the cells they provided a colour background for. Originally, the colour fields were sized and positioned individually by hand, but I seem to recall some potential for doing this with some somewhat obscure scripting if need be. I hope this account is not too confusing- it's a bit "ham fisted" and it may or may not have use for your particular requirements.
Regards,
Michael
-
- VIP Livecode Opensource Backer
- Posts: 10052
- Joined: Sat Apr 08, 2006 7:05 am
- Contact:
Re: Set a specific cell in a field to a different color
Nice approach, Mike.
Another option might be to make the field transparent and indicate selections with a graphic object beneath it. You can get the metrics for the object with a combination of the tabstops, the vScroll and hScroll, the borderWidth, and the effective textHeight, and use that to calculated where the selection indicator is drawn.
For discontiguous selection regions, note that you can set the points of a single polygon graphic object to render as any number of discontiguous shapes by putting blank lines between the points that comprise each shape.
Using a single polygon this way is so fast you may find the performance quite acceptable to render on-the-fly during the scrollbardrag message, so you can take full advantage of the size of text you can put into a field and still keep the selection indicator in synch with it.
It's a bit of work to set up, but you only need to do it once.
Another option might be to make the field transparent and indicate selections with a graphic object beneath it. You can get the metrics for the object with a combination of the tabstops, the vScroll and hScroll, the borderWidth, and the effective textHeight, and use that to calculated where the selection indicator is drawn.
For discontiguous selection regions, note that you can set the points of a single polygon graphic object to render as any number of discontiguous shapes by putting blank lines between the points that comprise each shape.
Using a single polygon this way is so fast you may find the performance quite acceptable to render on-the-fly during the scrollbardrag message, so you can take full advantage of the size of text you can put into a field and still keep the selection indicator in synch with it.
It's a bit of work to set up, but you only need to do it once.

Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
Re: Set a specific cell in a field to a different color
Hi Richard,
Yours,
Michael
... that’s something I certainly didn’t know, and would never have thought of. It’s definitely one for the Scrapbook. What I tried was one of those quick compromises which served immediate requirements. Because I was using different objects (fields) for each block of colour, experiments with scripting “bogged down” when it came to managing the multiple colour blocks. I’m glad I posted my attempt, as I’ve learnt from your response.For discontiguous selection regions, note that you can set the points of a single polygon graphic object to render as any number of discontiguous shapes by putting blank lines between the points that comprise each shape.
Yours,
Michael
-
- VIP Livecode Opensource Backer
- Posts: 10052
- Joined: Sat Apr 08, 2006 7:05 am
- Contact:
Re: Set a specific cell in a field to a different color
I learned of that trick with discontiguous shapes in a single polygon from Geoff Canyon's Start Battle - check this out:
http://www.inspiredlogic.com/rev/starbattle.rev
Everything you see on that screen is a single polygon object. Amazing work (and tons of fun to play with <g>).
http://www.inspiredlogic.com/rev/starbattle.rev
Everything you see on that screen is a single polygon object. Amazing work (and tons of fun to play with <g>).
Richard Gaskin
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
LiveCode development, training, and consulting services: Fourth World Systems
LiveCode Group on Facebook
LiveCode Group on LinkedIn
Re: Set a specific cell in a field to a different color
Michael,
you might have some fun at looking at alternating stripes for rows in a table field. A table field and a graphic with gradient does this. See the attached stack. It was more a try to get this going, but seems to work. I was tackling the problem in a different context anyway. Boy, to figure out what Rev does to the lines in a field, especially the first one, proved more difficult than I expected. But I think also a nice use of gradients.
As an exercise in patience on my part with regards to the table field see also
http://revonline2.runrev.com/stack/428/ ... agDividers
it lets you adjust the cell width according to content and you can drag the vertical dividers with the mouse.
As an exercise it is ok. Actually it should be all part of the table field object from the beginning.
regards
Bernd
you might have some fun at looking at alternating stripes for rows in a table field. A table field and a graphic with gradient does this. See the attached stack. It was more a try to get this going, but seems to work. I was tackling the problem in a different context anyway. Boy, to figure out what Rev does to the lines in a field, especially the first one, proved more difficult than I expected. But I think also a nice use of gradients.
As an exercise in patience on my part with regards to the table field see also
http://revonline2.runrev.com/stack/428/ ... agDividers
it lets you adjust the cell width according to content and you can drag the vertical dividers with the mouse.
As an exercise it is ok. Actually it should be all part of the table field object from the beginning.
regards
Bernd
Re: Set a specific cell in a field to a different color
@ Bernd
The stacks you posted really repay close study. The use of fillGradient to produce altenating bands of colour is very clever, when coordinated with the lines of a table field. Taking into account the special spacing of the first line is quite a challenge- I think I’ve stumbled over this at different times, without necessarily recognising it was textSize dependent. In order to update the image when changes are made to the textHeight, textSize, or margins of the table field, I tried this:
... in the script of the table field. I learnt a great deal from looking at your script, as well as the earlier “OldTableFieldDragDividers” stack. This must have been an exercise in patience, certainly not a task one could complete in a single sitting. Taking into account possible horizontal scroll of the table field was an interesting aspect, and adding the capability to have all the columns automatically the same width, or adjust to fit their contents, was a nice refinement. It’s good you took the trouble to place extensive comments in your script, so the stack is of lasting interest to other “LiveCoders”. In a word:
Ausgezeichnet!
Vielen Dank,
Michael
The stacks you posted really repay close study. The use of fillGradient to produce altenating bands of colour is very clever, when coordinated with the lines of a table field. Taking into account the special spacing of the first line is quite a challenge- I think I’ve stumbled over this at different times, without necessarily recognising it was textSize dependent. In order to update the image when changes are made to the textHeight, textSize, or margins of the table field, I tried this:
Code: Select all
on mouseEnter
if the textSize of me <> the myTextSize of me OR \
the textHeight of me <> the myTextHeight of me OR \
the margins of me <> the myMargins of me then
resizeControl
end if
end mouseEnter
on mouseLeave
set the myTextSize of me to the textSize of me
set the myTextHeight of me to the textHeight of me
set the myMargins of me to the margins of me
end mouseLeave
Ausgezeichnet!
Vielen Dank,
Michael
Re: Set a specific cell in a field to a different color
Michael,
thank you for your kind words. When I posted the above stack I was apparently so baffeld by the stripes that I did not notice, that the stripes dont follow the vertical scrolling of the table field. I added that to the stack I append below. The table field is really not suited for this kind of 'enhancement' since Rev does a lot of things behind your back. Very few messages get through that one can use to sync the vertical scrolling of the field and the stripes.
I hope I covered all possibilities and that the two always stay in sync. I added your mouseEnter/mouseLeave handlers, a very good idea to update the objects when text size etc was changed.
kind regards
Bernd
thank you for your kind words. When I posted the above stack I was apparently so baffeld by the stripes that I did not notice, that the stripes dont follow the vertical scrolling of the table field. I added that to the stack I append below. The table field is really not suited for this kind of 'enhancement' since Rev does a lot of things behind your back. Very few messages get through that one can use to sync the vertical scrolling of the field and the stripes.
I hope I covered all possibilities and that the two always stay in sync. I added your mouseEnter/mouseLeave handlers, a very good idea to update the objects when text size etc was changed.
kind regards
Bernd
- Attachments
-
- TableField with scrolling Stripes.rev.zip
- (4.85 KiB) Downloaded 306 times
Re: Set a specific cell in a field to a different color
Hi Bernd,
I haven’t done much previous work with table fields, so comparing the two stacks “alternatingLinesColorTablefield.rev” and “TableField with scrolling Stripes.rev” has been very instructive. To check my understanding of the latter stack, I believe it is structured thus:
stack "Table field with scrolling stripes"
---|
---card id 1002 (script)
------|
------group "tfGroup" (script)
------comprising:
------field "TF" (script)
------group "alGroup"
---------comprising:
---------graphic "alternatingLines"
The main script the user’s mouse interacts with is in field "TF”- it is the resizeControl in this script that “synchronises” the graphic “alternatingLines” with the lines in field “TF”. The user operates the scrollbars of field “TF” to navigate the table field. The scrollBarDrag handler in field “TF” makes the vScroll of group “alGroup” match the vScroll of field “TF”. The advantage of making the graphic "alternatingLines" into the group "alGroup" is that it becomes scrollable, facilitating synchronising its scroll with that of field "TF". In the resizeControl handler, the "lock screen" command is accidentally commented out (just before “the owner of me is group “Tfgroup” comment), making resizing not as smooth as intended (indicated by the “unlock screen” later on). I was interested in the use of the “max” function to ensure the width of the graphic "alternatingLines" is never less than 0- I was not aware of this function, and it’s handy to know.
Getting the alternating stripes scrollable with the table field is definitely “easier said than done”. The problem is, you can add new lines to the table field by clicking in the lowest line of cells. This “shifts” all the previous lines upwards, and the alternating stripes should follow. However, the scroll changes, without generating a scrollBarDrag message. The “mouseDown” work-around is very elegant.(I well know the importance of locking messages when you set a scroll, if there is also a scrollBarDrag handler involved- the “lock up loop” I experienced when I neglected this was quite memorable.) From the seemingly simple “let’s make the alternating stripes scroll with the table field” a whole chain of implications follow- making graphic “alternatingLines” very large, then “packaging” everything in group “tfGroup”, then having a resizeControl handler in the script of group “tfGroup” to allow the user to resize the whole assembly correctly (necessitating the nice “selectedGroupControls” test) ... every piece must be in place for things to work correctly.
There’s another scenario to cover- if the down arrow is pressed repeatedly, it gets to the bottom of the visible table field then starts to add lines. Somehow the graphic “alternatingLines” must be made to scroll to match. rawKeyDown messages are sent to the focused control, and then on to the card. It's interesting that rawKeyDown does not go to the table field when you type in a cell, hence it is evidently not the focused object when you type, so the message goes to the card instead (as per the Rev Dictionary). We can conclude that Rev must be creating fields "on the fly", and when you click elsewhere, or hit the enter key, Rev uses the contents of the temporary field to update the text property of the table field itself, then deletes the temporary field. You can see this process in action if you place an object partially obscuring the table field, then press the arrow key repeatedly. The temporary field is created over its position in the cell (visible over the obscuring object because the new temporary field is created on top of everything else). Another thing I thought to try was putting:... in a frontScript, which lets you see the name of the cell, and its id. We can also see that the temporary field is the focused object, and thus if we are to respond to the rawKeyDown message, we have to put the rawKeyDown handler in the card script.
It’s interesting that the arrowKey message itself is not passed- this I imagine has something to do with the frontScript Rev uses to implement the table field. The rawKeyDown handler that triggers the “adapt” handler is the work-around that gets the graphic “alternatingLines” to synchronise with the table field when the “down” arrow is pressed. (One thing I wasn’t entirely sure of is why “adapt” had to be sent, rather than being incorporated in the rawKeyDown conditional).
I suspect the problem with the scroll resetting to 0 if you edit a cell, then click in another cell, is also buried in one of Rev's frontScripts:
button id 1116 of group id 1016 of card id 1002 of stack "C:/Program Files/Revolution Studio/4.0.0-gm-1/Toolset/revlibrary.rev"
... seems a likely candidate (of course, the path to the stack may be different on your computer, but I imagine the id’s are the same).
Looking at the frontScript which implements table fields offers a useful perspective. It’s not an easy thing to achieve, and in fairness to the original programmer/s it would be more reasonable to regard table fields as appreciably enhanced text fields, rather than as deficient datagrids. Table fields give a useful “add on” to a normal text field, lending it basic “spreadsheet-like” behaviour, though as we have seen, it is difficult to take it much further. The simplicity of table fields suffices in many circumstances.
This post is rather long, and while it serves to test my understanding, I hope there is also something of interest to others, who may be encouraged to inspect the relevant stacks.
Regards,
Michael
I haven’t done much previous work with table fields, so comparing the two stacks “alternatingLinesColorTablefield.rev” and “TableField with scrolling Stripes.rev” has been very instructive. To check my understanding of the latter stack, I believe it is structured thus:
stack "Table field with scrolling stripes"
---|
---card id 1002 (script)
------|
------group "tfGroup" (script)
------comprising:
------field "TF" (script)
------group "alGroup"
---------comprising:
---------graphic "alternatingLines"
The main script the user’s mouse interacts with is in field "TF”- it is the resizeControl in this script that “synchronises” the graphic “alternatingLines” with the lines in field “TF”. The user operates the scrollbars of field “TF” to navigate the table field. The scrollBarDrag handler in field “TF” makes the vScroll of group “alGroup” match the vScroll of field “TF”. The advantage of making the graphic "alternatingLines" into the group "alGroup" is that it becomes scrollable, facilitating synchronising its scroll with that of field "TF". In the resizeControl handler, the "lock screen" command is accidentally commented out (just before “the owner of me is group “Tfgroup” comment), making resizing not as smooth as intended (indicated by the “unlock screen” later on). I was interested in the use of the “max” function to ensure the width of the graphic "alternatingLines" is never less than 0- I was not aware of this function, and it’s handy to know.
Getting the alternating stripes scrollable with the table field is definitely “easier said than done”. The problem is, you can add new lines to the table field by clicking in the lowest line of cells. This “shifts” all the previous lines upwards, and the alternating stripes should follow. However, the scroll changes, without generating a scrollBarDrag message. The “mouseDown” work-around is very elegant.(I well know the importance of locking messages when you set a scroll, if there is also a scrollBarDrag handler involved- the “lock up loop” I experienced when I neglected this was quite memorable.) From the seemingly simple “let’s make the alternating stripes scroll with the table field” a whole chain of implications follow- making graphic “alternatingLines” very large, then “packaging” everything in group “tfGroup”, then having a resizeControl handler in the script of group “tfGroup” to allow the user to resize the whole assembly correctly (necessitating the nice “selectedGroupControls” test) ... every piece must be in place for things to work correctly.
There’s another scenario to cover- if the down arrow is pressed repeatedly, it gets to the bottom of the visible table field then starts to add lines. Somehow the graphic “alternatingLines” must be made to scroll to match. rawKeyDown messages are sent to the focused control, and then on to the card. It's interesting that rawKeyDown does not go to the table field when you type in a cell, hence it is evidently not the focused object when you type, so the message goes to the card instead (as per the Rev Dictionary). We can conclude that Rev must be creating fields "on the fly", and when you click elsewhere, or hit the enter key, Rev uses the contents of the temporary field to update the text property of the table field itself, then deletes the temporary field. You can see this process in action if you place an object partially obscuring the table field, then press the arrow key repeatedly. The temporary field is created over its position in the cell (visible over the obscuring object because the new temporary field is created on top of everything else). Another thing I thought to try was putting:
Code: Select all
on mouseMove
if the shiftKey is down then
put (the name of the mouseControl)&return&(the focusedObject)
end if
pass mouseMove
end mouseMove
It’s interesting that the arrowKey message itself is not passed- this I imagine has something to do with the frontScript Rev uses to implement the table field. The rawKeyDown handler that triggers the “adapt” handler is the work-around that gets the graphic “alternatingLines” to synchronise with the table field when the “down” arrow is pressed. (One thing I wasn’t entirely sure of is why “adapt” had to be sent, rather than being incorporated in the rawKeyDown conditional).
I suspect the problem with the scroll resetting to 0 if you edit a cell, then click in another cell, is also buried in one of Rev's frontScripts:
button id 1116 of group id 1016 of card id 1002 of stack "C:/Program Files/Revolution Studio/4.0.0-gm-1/Toolset/revlibrary.rev"
... seems a likely candidate (of course, the path to the stack may be different on your computer, but I imagine the id’s are the same).
Looking at the frontScript which implements table fields offers a useful perspective. It’s not an easy thing to achieve, and in fairness to the original programmer/s it would be more reasonable to regard table fields as appreciably enhanced text fields, rather than as deficient datagrids. Table fields give a useful “add on” to a normal text field, lending it basic “spreadsheet-like” behaviour, though as we have seen, it is difficult to take it much further. The simplicity of table fields suffices in many circumstances.
This post is rather long, and while it serves to test my understanding, I hope there is also something of interest to others, who may be encouraged to inspect the relevant stacks.
Regards,
Michael
Re: Set a specific cell in a field to a different color
Michael,
you describe the structure of the stack and what Rev does with the temporary fields very clearly and concise. I always find it fascinating when someone grasps the logic and can explain it also. I am a lot less systematic in my approach.
You even ventured into the realms of frontscripts, where I did not go. I used the behavior of the table field and the temporary field as guidance. (a complex system describes itself by its behavior). But you went on deeper into the topic, and more appropriately so.
max function: you probably read in the dictionary. What I find very handy is from the dictionary:
Kind regards
Bernd
you describe the structure of the stack and what Rev does with the temporary fields very clearly and concise. I always find it fascinating when someone grasps the logic and can explain it also. I am a lot less systematic in my approach.
You even ventured into the realms of frontscripts, where I did not go. I used the behavior of the table field and the temporary field as guidance. (a complex system describes itself by its behavior). But you went on deeper into the topic, and more appropriately so.
I did not want to tie adapt to the rawkeyDown message but it should trigger right after the message was passed. Turns out this made for a lot faster response than what I had previously. I suppose (did not test) that the rawkeyDown -> rawkeyUp finishes before the "adapt" message gets handled. I used to have adapt in a rawkeyUp handler and it was slower.One thing I wasn’t entirely sure of is why “adapt” had to be sent, rather than being incorporated in the rawKeyDown conditiona
max function: you probably read in the dictionary. What I find very handy is from the dictionary:
again thank your for taking the time to look at the stack and explaining it so brilliantly.You can use the max and min functions together to limit a value to a certain range. For example, the expression
max(10,min(myValue,100))
yields a number between 10 and 100. If myValue is within the limits, the expression is equal to myValue; if it is greater than 100, the expression evaluates to 100; and if it is less than 10, the expression evaluates to 10.
Kind regards
Bernd