1. EuGTK - setRow
- Posted by Jerry_Story Sep 20, 2010
- 1476 views
global object lvNutrientsREQ = CreateLV(20) -- 20 seems to be the number of rows, not columns. global constant lstNutrientsREQ = List:View(lvNutrientsREQ,{"REQ nutrient","in 100g food","in diet"}) global object storeNutrientsREQ = List:Store({gSTR,gSTR,gSTR})
./eugtk_stuff/ListView.e:55 in procedure setCol() subscript value 21 is out of bounds, reading from a sequence of length 20 ... called from ./eugtk_stuff/ListView.e:63 in procedure setRow() ... called from ./dmak_actions.e:806 in procedure DisplayNutrientsREQ()This is line 806.
setRow(i,lstNutrientsREQ,lvNutrientsREQ,"background",colors[color])
Clearly, 20 is plenty large if that is the number of columns. If I give it a ridiculously large number, enough for the number of items in the list, this error message does not happen.
In the case of lvFoods, that would be a major large number, because the number of foods in the USDA data is 7500+.
lvFoods = CreateLV(7600)
Is that correct?
2. Re: EuGTK - setRow
- Posted by irv Sep 21, 2010
- 1472 views
No, CreateLV returns an iterator, and a sequence of n text renderers, one for each column in your list. So, 4 columns should use CreateLV(4)
Now, the reason you are getting the error is because setRow doesn't do what you think it does - nope, that would be too easy.
Think about it for a minute: if you were to set the 4th row from the top to be colored red, for example, what would happen when you sort or drag the data in that row somewhere else? The red wouldn't move with the data, and that would normally be what you would want it to do, I think. At least, that's what the people who wrote GTK thought.
So... setRow needs the following parameters:
- a COLUMN # or a range of COL #'s: {start, fini} that you want to have this color or font
- the tv
- the lv
- a string specifying "background", "foreground", or "font"...
- a COLUMN # in your store which contains a color description - "red". for example, to be associated with this item
A column must be declared in your store to hold this string, so it is declared as a gSTR (in List:Store()) You probably don't want to display the strings, so you do not declare a column to show this (in List:View()) Clear as mud yet?
That way, in your list of foods, all the green veggies would have a shade of green "lightgreen", "darkgreen", etc. in the COLOR column, all the red meats could have a shade of red.... etc.
So when you move Broccoli around in the list, Broccoli's nice green color moves with it.
If you just want an entire column to be one color, you can use setCol with the color spelled out as a string. If you just want more than one column to be one color, you can - strangely enough - use setRow({2,4}..."red"). No, it doesn't make any sense.
Looks like setRow needs a more descriptive name. SetTheColorOfTheItemInColumn:n,UsingTheColorNameStoredWithThatRow()
object names = { {"Jerry S. Smith",21,"Rover","red","lightgray","Courier 12"}, {"Jonnie B. Goode",44,"Fluffy"}, {"Susan Black",45}, {"Fred Flintstone",55, "Dino", "cyan", "blue", "Beat My Guest 16"}, {"George Burns",112,"cigar","white","red", ""} } -- note: you do not need to fill in more that required - if, like Susan, you don't HAVE a pet, leave it out. -- if Susan had no pet, but we still needed to set a background color for her, we could write: -- {"Susan Black",45,0,"cyan"... the zero gets skipped over, leaving the 'pet' blank -- -- note2: we can't skip over a number like we can with a string - if we leave off Susan's age, -- it will display as zero.
3. Re: EuGTK - setRow
- Posted by Jerry_Story Sep 21, 2010
- 1407 views
I'm still confused.
setRow(i, lstNutrientsREQ, lvNutrientsREQ, "background", colors[color])
What I want to do is set row i to the color. How can that be done?
If i indicates column (vertical) and not row (horizontal), then what indicates row?
The list will sometimes be re-sorted but when it is, it is also re-colored, so the colors don't need to follow the items.
The color of an item changes. It changes according to the amount of the nutrient. Green means enough. Red means too much.
4. Re: EuGTK - setRow
- Posted by irv Sep 22, 2010
- 1371 views
I'm still confused.
setRow(i, lstNutrientsREQ, lvNutrientsREQ, "background", colors[color])
What I want to do is set row i to the color. How can that be done?
If i indicates column (vertical) and not row (horizontal), then what indicates row?
The list will sometimes be re-sorted but when it is, it is also re-colored, so the colors don't need to follow the items.
The color of an item changes. It changes according to the amount of the nutrient. Green means enough. Red means too much.
This isn't clear - you're saying the color doesn't follow the item, then you're saying it changes according to the amount of the nutrient.
Can you give me an example or a picture of what you're trying to do?
5. Re: EuGTK - setRow
- Posted by DanM Sep 22, 2010
- 1333 views
I'm still confused.
setRow(i, lstNutrientsREQ, lvNutrientsREQ, "background", colors[color])
What I want to do is set row i to the color. How can that be done?
If i indicates column (vertical) and not row (horizontal), then what indicates row?
The list will sometimes be re-sorted but when it is, it is also re-colored, so the colors don't need to follow the items.
The color of an item changes. It changes according to the amount of the nutrient. Green means enough. Red means too much.
This isn't clear - you're saying the color doesn't follow the item, then you're saying it changes according to the amount of the nutrient.
Can you give me an example or a picture of what you're trying to do?
Just a guess, and I apologize for butting in, but I think he means that the food item exists in a column in which the color indicates a nutritional assessment, and if its nutritional assessment changes, it will be moved to another column, which would have a different color appropriate to the amount of nutrient, therby not bringing with it the previous color it had.
That is, an item's color changes when moved, to the color of the place it's *moved* to (thereby not carrying its color *with* it), because the place it's moved to relates to and indicates its newly assesed nutritional value.
I think that's right?
Dan
6. Re: EuGTK - setRow
- Posted by irv Sep 22, 2010
- 1339 views
If you want the colors to be based on, let's say, the percentage of a nutrient in relation to a minimum daily requirement, something like the following would work:
include GtkEngine.e include std/machine.e include ListView.e as LV -- -- note: see http://sedition.com/perl/rgb.html for a chart, -- or google 'xcolors' to find names of all available colors -- enum NAME, NUT, SERV constant names = { {"Asparagus, raw",3,8}, {"Beet greens, boiled",164,12}, {"Broccoli, raw",43,14}, {"Cabbage, boiled",36,6}, {"Chard, swiss, boiled",102,5}, {"Collards, boiled",266,4}, {"Onions, raw",37,10} } sequence bkgnds = {"red2","Orange Red","sandy brown","wheat2","green yellow","Pale Green","green1","green2","green3","green4"} function PercentMDR(atom ignore, atom rend, atom model, atom iter, atom col=0) integer MDR = 600 atom result = allocate(8) get(model,"get",iter,NUT-1,result,-1) -- gets the amt of nutrient from NUT column integer amt = peek4u(result) get(model,"get",iter,SERV-1,result,-1) integer servsize = peek4u(result) amt = amt * servsize atom percent = floor((amt/MDR)*100) -- figure as percent of mdr if percent > 100 then percent = 100 end if if percent < 10 then percent = 10 end if ifdef DEBUG then printf(1,"%d / %d = %d \n",{amt,MDR,percent}) end ifdef set(rend,"background",bkgnds[percent/10]) -- select color 1..10 return 1 end function constant percent_mdr = call_back(routine_id("PercentMDR")) object lv = LV:Iter(2) constant tv = LV:View(lv,{"Name","Nutrient (mg)"}) -- {column headings} set(tv,"reorderable",TRUE) set(tv,"rules hint",TRUE) -- shade alternate lines set(tv,"grid lines",GTK_TREE_VIEW_GRID_LINES_BOTH) constant img = create(GtkImage,"/home/irv/demos/tiphat.gif") constant win = create(GtkWindow) connect(win,"destroy",quit) set(win,"modify bg",0,"lightgray") set(win,"border width",5) constant panel = create(GtkVBox) add(win,panel) add(panel,tv) object store1 = LV:Store({gSTR,gINT,gINT}) -- {column data types} set(tv,"model",store1) setCellDataFunc(1,tv,lv,percent_mdr,NUT) -- 1 for each column you want colored setCellDataFunc(2,tv,lv,percent_mdr,NUT) for i = 1 to length(names) do -- load the list store with data LV:Row(lv,store1,names[i]) end for show_all(win) main()
This requires an updated ListView.e:
include GtkEngine.e include std/machine.e enum ITER, RENDERERS export function Iter(integer cols) object x = {} object rend for i = 1 to cols do rend = create(GtkCellRendererText) x = append(x,rend) end for atom iter = allocate(32) return {iter,x} end function function addColumn(atom tv, object renderer, sequence title, integer datacolumn) set(tv,"insert column with attributes",-1,title,renderer,"text",datacolumn) return 1 end function enum FGND,BKGD export function View(sequence lv, object cols) atom tv = create(GtkTreeView) atom col -- add for i = 1 to length(cols) do addColumn(tv,lv[RENDERERS][i],cols[i],i-1) col = get(tv,"column",i-1) -- add register_object(col,GtkTreeViewColumn) -- add end for return tv end function export function Store(object p) while length(p) < 8 do p &= 0 end while return create(GtkListStore,p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8]) end function export function Row(sequence lv, atom store, object data, integer position=99999) set(store,"insert",lv[ITER],position) for i = 1 to length(data) do set(store,"set",lv[ITER],i-1,data[i],-1) end for return 1 end function export function setCellDataFunc(object n, object tv, object lv, atom fn, atom data=0) if sequence(n) then for i = 1 to length(n) do setCellDataFunc(n[i],tv,lv,fn,data) end for return 1 else atom x = get(tv,"column",n-1) set(x,"cell data func",lv[RENDERERS][n],fn,data) end if return 1 end function export procedure setCol(integer x, object tv, object lv, sequence attr, object datacolumn) atom col = get(tv,"column",x-1) if sequence(datacolumn) then datacolumn = allocate_string(datacolumn) set(lv[RENDERERS][x],attr,datacolumn) else set(col,"add attribute",lv[RENDERERS][x],attr,datacolumn) end if end procedure export procedure setRow(object x, object tv, object lv, sequence attr, object datacol) if atom(x) then setCol(x+1, tv, lv, attr, datacol) else for i = x[1] to x[2] do setCol(i+1, tv, lv, attr, datacol) end for end if end procedure
7. Re: EuGTK - setRow
- Posted by irv Sep 22, 2010
- 1401 views
Problem here is that we're wanting to change the color of a row, and there's no such thing as a row. Only columns with n items in each column. Put 2 or more columns side by side, and you have - visually - a row. But it's not a row, it's still just columns side by side.
Example:
Say you're washing dishes in a restaurant. There are three stacks of plates, and you notice that the third plate from the top of each pile is cracked.
These plates appear to form a row of cracked plates, so you remove the third row of plates and discard them, right? Just grab the 3rd row of plates and pull it out.
Not gonna work, because the only connection between those 3 cracked plates is in your eye and mind. (and the abstract fact that they happen to be, at the moment, third from the top)
You have to remove plate #3 (or #2, if you're a C programmer and can't count) from stack 1, and plate #3 from stack 2, and plate #3 from stack 3.
So, to change the color of a "row" we change the color of the nth item in each column.
But what do we mean by nth item?
Do we want to change the color of the third item on the list, or the third item that is currently showing?
Since you can scroll a list, sort it differently, and move items around, you have to decide whether you want to:
- (a) color the nth "row" from the top, no matter what its contents, so the color remains fixed in place on the screen.
- (b) color the nth "row" in the list, so the color scrolls with & follows the contents.
- oh, and (c) decide if this is really the best way to accomplish whatever it is we are trying to do.
8. Re: EuGTK - setRow
- Posted by Jerry_Story Sep 22, 2010
- 1387 views
This isn't clear - you're saying the color doesn't follow the item, then you're saying it changes according to the amount of the nutrient.
Can you give me an example or a picture of what you're trying to do?
Here is a screenshot of the wxEuphoria version of this program.
http://freshmeat.net/screenshots/9a/69/9a6932dfa56e21a303240713bc7adb03_medium.png?1237051040
In the screenshot, most of the nutrients are green. That means they are within the range between too much and too little. One nutrient, water, is red. That means too much water. The colors of the nutrients will be changed as they become too much or not enough or the right amount.
9. Re: EuGTK - setRow
- Posted by Jerry_Story Sep 22, 2010
- 1343 views
This isn't clear - you're saying the color doesn't follow the item, then you're saying it changes according to the amount of the nutrient.
Can you give me an example or a picture of what you're trying to do?
Just a guess, and I apologize for butting in, but I think he means that the food item exists in a column in which the color indicates a nutritional assessment, and if its nutritional assessment changes, it will be moved to another column, which would have a different color appropriate to the amount of nutrient, therby not bringing with it the previous color it had.
That is, an item's color changes when moved, to the color of the place it's *moved* to (thereby not carrying its color *with* it), because the place it's moved to relates to and indicates its newly assesed nutritional value.
I think that's right?
Dan
Nope. The nutrient name stays where it is. It is not moved to another column. It's a nutrient, not a food. Nothing is moved. Nothing is changed except the color of the row. When the amount is less than 100%, it is white. When the amount is 100% but less than excess, it is green. When the amount is excess (whatever excess is for that particular nutrient), it is red.
It is not necessary for the color to follow the item, because the items get re-colored anyway every time they are re-sorted.
10. Re: EuGTK - setRow
- Posted by Jerry_Story Sep 22, 2010
- 1363 views
Since you can scroll a list, sort it differently, and move items around, you have to decide whether you want to:
- (a) color the nth "row" from the top, no matter what its contents, so the color remains fixed in place on the screen.
- (b) color the nth "row" in the list, so the color scrolls with & follows the contents.
- oh, and (c) decide if this is really the best way to accomplish whatever it is we are trying to do.
(b) is correct. Row n is green. No matter how it is scrolled, row n in the list is still green. It might not be the nth row showing.
This is how it's done in wxEuphoria.
[proc] set_list_item_back_color ( atom list, atom item, atom color ) Category: wxListCtrl Sets the background color of a wxListCtrl item. * list the parent wxListCtrl of the item * item the index of the item (this is the number returned by insert_listctrl_item()) * color a wxColour objectThe question is: how to do the same thing in EuGTK.
11. Re: EuGTK - setRow
- Posted by irv Sep 22, 2010
- 1316 views
So the color is computed, and must follow the item - as in, you'd always want the red and the 364.3% to be wherever in the list Water might be (even when sorted differently).
So the color "red" isn't attached to the Water item, but needs to be selected based on the current percentage for that item.
The above program I posted shows how to do that. (Except you'll probably want to change the order of the colors, if not the colors themselves) I've got the lowest in red, the highest in darker colors of green. As you can see, it would be easy to have only 2 or 3 colors - "too low", "ok", and "too high", perhaps.
12. Re: EuGTK - setRow
- Posted by irv Sep 24, 2010
- 1419 views
Now that all that discussion is over, and we've figured out how to set colors of rows, DON'T DO IT
Please consider why that is deemed to be a bad idea. Impolite, at best, and rendering your app unusable at worst.
Themes are very popular with users of Linux - Windows, too, for that matter - and many themes change the colors of things - for example, a dark theme like Azenis Red will have a black background, and the selected row on a ListView will be RED.
Now, you go and color other rows RED also. How does the user know which row is selected? Ans: he can't. Worse, whatever row is currently selected now appears to be "over the limits", even if it's zero!
Overriding the user-selected colors and fonts, etc is also rude to people with limited vision. Like me.
Therefore, the proper and polite way to do something like this might be to pop up a warning list of items that exceed limits.