
------------------------------------------------------------------------
--# GtkListView demo - gaudy, but shows most all functions
--
-- LOOKS COMPLICATED, but not really so bad, since I have used 
-- a lot more features than would normally be used, just for
-- demo purposes.
--
-- Study it, you'll see how to accomplish almost anything with
-- simple functions which should be familiar to Euphorians.
------------------------------------------------------------------------

include GtkEngine.e

constant docs = `<u><b>GtkListView</b></u>
    This demos creating and retrieving data from a listview.
    The list can be rearranged by dragging a veggie up or down 
    the list. Double-click a row, or select one or more, then 
    click buttons at bottom.
`
enum NAME,PREP,MG,MDR,COLOR,NOTE

sequence veggies = { -- a totally bogus list of food values; last field is 'editable' flag;
    {"Broccoli",			"raw",		43,		64,	"green",	0,	0},
    {"Cabbage",				"boiled",	103,    16,	"cyan",		0,	1},
    {"<b>Beet</b> greens",	"steamed",	164,    72,	"red",		0,	0},
    {"<i>Swiss Chard</i>",	"boiled",	102,    50,	"green",	0,	1},
    {"Collards",			"boiled",	266,    10,	"skyblue",	0, 	0},
    {"Asparagus",			"",			23,     18,	"yellow",	0,	1},
    {"Onions",				"raw",		10,     34,	"white",	0,	0}
}

constant -- extra non-veggie selections (used later)
    Steak = 	{"Steak",			"Grilled",	2,	3,	"#FEC277",	"Yum!",    	1},
    Chicken = 	{"Chicken",			"Grilled",	2,	3,	"#FE4377",	"Cluck!",  	1},
    Duck = 		{"Duck",			"Roasted",	22,	4,	"#FE4342",	"Quack!",  	1},
    Pie = 		{"Apple Pie",		"Baked",	0,	0,	"pink",		"One Pie", 	0},
    Pudding =   {"Possum Pudding",	"Baked",  155, 90,	"limegreen","One Slice",0}
    
------------------------------------------------------------------------
-- Create a model and store the veggies in it;
------------------------------------------------------------------------
object store = create(GtkListStore,{gSTR,gSTR,gINT,gINT,gSTR,gSTR,gINT})

    set(store,"data",veggies)

------------------------------------------------------------
-- Create the view, and set appearance
------------------------------------------------------------
constant tv  = create(GtkTreeView,{ 
    {"model",store},
    {"reorderable",TRUE},
    {"headers clickable",TRUE},
    {"rules hint",TRUE},
    {"grid lines",GTK_TREE_VIEW_GRID_LINES_BOTH},
    {"margin left",10},
    {"margin right",10},
    {"margin bottom",10},
    {"rubber banding",TRUE}})
    
constant -- columns (don't really need to set all these properties, this is gaudy!)
    col1 = create(GtkColumn,"title=Name,type=text,markup=1,background=5,editable=7"),
    col2 = create(GtkColumn,"title=Prep,type=text,text=2,editable=7,placeholder-text=6"),
    col3 = create(GtkColumn,"title=Ounces,type=text,text=3,renderer.background=grey90"),
    col4 = create(GtkColumn,"title=%MDR,type=progress,value=4,sort_column_id=4")
    set(tv,"append columns",{col1,col2,col3,col4})

constant selection = get(tv,"selection") 
    set(selection,"mode",GTK_SELECTION_MULTIPLE)

-- to catch a double-click, uncomment the following line:
/*
   connect(tv,"row-activated",call_back(routine_id("ShowSelected")))
*/
   -- note that double-clicking is not completely compatible with editable rows,
   -- as the same double click can either initiate editing or call the callback,
   -- which can be confusing. A pop-up menu on right button click with an "edit"
   -- option might be better in this case.
  
----------------------------------------------------------
-- Create main window and run the program;
----------------------------------------------------------
constant win = create(GtkWindow,
    "title=`List View`,size=400x460,border_width=8,position=1")
    connect(win,"destroy","Quit")

constant panel = add(win,create(GtkBox,VERTICAL))
constant lbl = add(panel,create(GtkLabel,{{"markup",docs}}))

constant scroller = create(GtkScrolledWindow)
    pack(panel,scroller,TRUE,TRUE)
    add(scroller,tv)
    
-- Enable the following if you want a permanently visible search box:
-- Otherwise, ctl-f will pop up a search box
/*
constant srch = create(GtkEntry)
    pack(panel,srch)
*/

---------------------------------
function NewBtn(object params) -- helper function to build a bunch o'buttons
---------------------------------
atom btn = create(GtkButton,params[1],_(params[2]))
    set(btn,"tooltip markup",params[3])
    set(btn,"size request",120,30)
return btn
end function

object btns = { -- button image#caption, function, tooltip;
    {"go-bottom#_Append","AppendRow","Click to append a dessert"},
    {"go-top#_Prepend","PrependRow","Click to prepend a Steak"},
    {"insert-object-symbolic#_Insert","InsertRow","Click to insert a Duck after selected item"},
    {"gtk-delete","DeleteRow","Click to delete the selected row"},
    {"emblem-synchronizing#_Replace","ReplaceRow","Replace the selected row(s) with a tasty treat"},
    {"format-justify-fill#List","ShowAll","Click to show listing on terminal"},
    {"starred#_Selected","ShowSelected","Click to show selected item(s)"},
    {"gtk-info","ShowInfo","Click to show info about model"},
    {"gtk-quit","Quit","Click to exit"},
    {"media-playlist-shuffle#Swap","SwapItems","Click to swap two selected items"},
    {"go-down#After","MoveAfter","Moves first selected item to a position immediately <i>after</i> the second"},
    {"go-up#_Before","MoveBefore","Moves first selected item to a position immediately <i>before</i> the second"}
}
 
for i = 1 to length(btns) do
    btns[i] = NewBtn(btns[i])
end for     

ifdef WINDOWS then
	set(btns[8],"sensitive",FALSE)
	set(btns[8],"tooltip text","Broken on Windows")
end ifdef

constant box1 = create(GtkButtonBox) add(box1,btns[1..4]) 
constant box2 = create(GtkButtonBox) add(box2,btns[5..8])
constant box3 = create(GtkButtonBox) add(box3,btns[9..12])
pack(panel,{box1,box2,box3})

show_all(win)
main()

-- Edit function is not used here
---------------------------------------------------------
function EditName(atom rend, object path, object newtext)
---------------------------------------------------------
atom row = get(selection,"selected row") 
    set(store,"col data",row,1,peek_string(newtext))
return 1
end function

--------------------------
function ShowSelected() -- get one or more selected rows;
--------------------------
object rows = get(selection,"selected rows") 
object results = {}
object names = {}

if length(rows) then
    for i = 1 to length(rows) do 
        results = append(results, get(store,"col data",rows[i],1))
    end for
    results = join(demarkup(results),'\n')
    Info(win,,"You chose",results)
end if

return 1
end function 

---------------------
function ShowAll() -- get data back as a Eu sequence
---------------------
object x = get(store,"data") --update the original list
       x = vslice(x,1) 
       x = demarkup(x)
       display(x) -- and display on the terminal
return 1
end function

--------------------
function AppendRow()
--------------------
object data = set(store,"append row",Pie)
return 1
end function 

---------------------
function PrependRow()
---------------------
object data = set(store,"prepend row",Steak)
return 1
end function

-----------------------------------------------------------------------------------------
-- note: nearly all the following calls require some testing to be sure
-- the user has selected the correct number of items from the list.
-- e.g: you cannot swap one item, nor is swapping 3 items logical.
------------------------------------------------------------------------------------------

--------------------
function InsertRow()
--------------------
object row = get(selection,"selected row")

    if row > 0 then
	set(store,"insert row",Duck,row+1)
    else
	Warn(,,"No row selected","Select a row first")
    end if
    
return 1
end function

--------------------
function DeleteRow()
--------------------
object rows = get(selection,"selected rows") 

    if equal({},rows) then
	Warn(,,"No row(s) selected to delete")
    else
	for i = length(rows) to 1 by -1 do
	    set(store,"remove row",rows[i])
	end for
    end if
    
return 1
end function 

---------------------
function ReplaceRow()
---------------------
object rows = get(selection,"selected rows") 

    if length(rows) = 0 then
	return Warn(win,"Too Bad",
	    "You didn't select anything!",
	    "Try clicking on one or more rows")
    end if
    for i = 1 to length(rows) do
	set(store,"replace row",Pudding,rows[i])
    end for
    
return 1
end function 

--------------------
function SwapItems()
--------------------
object rows = get(selection,"selected rows") 

    if length(rows) = 2 then
	set(store,"swap rows",rows[1],rows[2])
    else
	Error(win,,"Sorry",
	    "Must select exactly two rows to be swapped!")
    end if
    
return 1
end function

---------------------
function MoveBefore()
---------------------
object rows = get(selection,"selected rows")

    if length(rows) = 2 then
	set(store,"move before",rows[1],rows[2])
    else
	Error(win,,"Sorry","Must select exactly two rows!")
    end if
    
return 1
end function

--------------------
function MoveAfter()
--------------------
object rows = get(selection,"selected rows")

    if length(rows) = 2 then
	set(store,"move after",rows[2],rows[1])
    else
	Error(win,,"Sorry","Must select exactly two rows!")
    end if
    
return 1
end function

----------------------
function ShowInfo() -- statistics;
---------------------- 
integer rows = get(store,"n rows") 
integer cols = get(store,"n cols") 
integer sortcol = get(store,"sort column id")
integer sortord = get(store,"sort order")
		
    if get(store,"is sorted") then
	Info(win,,"Model Contains",
	    sprintf("%d rows, %d columns\nSorted on col %d order %d",
		{rows,cols,sortcol,sortord}))
    else
	Info(win,,"Model contains",
	    sprintf("%d rows, %d columns",{rows,cols}))
    end if  
    
return 1
end function

------------------------------
function demarkup(object x) -- remove markup
------------------------------
integer st,fi

    for i = 1 to length(x) do -- need plain text when displaying on terminal;
	while st > 0 and fi > st with entry do
	    x[i] = remove(x[i],st,fi)
	entry
	    st = find('<',x[i]) fi = find('>',x[i])
	end while
    end for
    
return x
end function
