1. EuGTK - setRow

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?

new topic     » topic index » view message » categorize

2. Re: EuGTK - setRow

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:

  1. a COLUMN # or a range of COL #'s: {start, fini} that you want to have this color or font
  2. the tv
  3. the lv
  4. a string specifying "background", "foreground", or "font"...
  5. 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. 
 
new topic     » goto parent     » topic index » view message » categorize

3. Re: EuGTK - setRow

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.

new topic     » goto parent     » topic index » view message » categorize

4. Re: EuGTK - setRow

Jerry_Story said...

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?

new topic     » goto parent     » topic index » view message » categorize

5. Re: EuGTK - setRow

irv said...
Jerry_Story said...

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

new topic     » goto parent     » topic index » view message » categorize

6. Re: EuGTK - setRow

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 
new topic     » goto parent     » topic index » view message » categorize

7. Re: EuGTK - setRow

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.
new topic     » goto parent     » topic index » view message » categorize

8. Re: EuGTK - setRow

irv said...

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.

new topic     » goto parent     » topic index » view message » categorize

9. Re: EuGTK - setRow

DanM said...
irv said...

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.

new topic     » goto parent     » topic index » view message » categorize

10. Re: EuGTK - setRow

irv said...

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 object  
The question is: how to do the same thing in EuGTK.

new topic     » goto parent     » topic index » view message » categorize

11. Re: EuGTK - setRow

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.

new topic     » goto parent     » topic index » view message » categorize

12. Re: EuGTK - setRow

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.

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu