------------------------------------------------------------------------ --# 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 = `GtkListView 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}, {"Beet greens", "steamed", 164, 72, "red", 0, 0}, {"Swiss Chard", "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 after the second"}, {"go-up#_Before","MoveBefore","Moves first selected item to a position immediately before 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