1. 7GUIs

Eric Wing said...

Subject: [Iup-users] 7GUIs GUI comparison
To: "IUP discussion list." <iup-users@lists.sourceforge.net>
Date: Friday, 17 November, 2017, 1:19

I saw this on HackerNews or Reddit yesterday. https://github.com/eugenkiss/7guis/wiki

Its origins are from a research paper that compares the objected oriented and functional programming for GUI design. http://www.eugenkiss.com/projects/thesis.pdf

While that falls outside the scope of what IUP cares about, I did think the 7 GUI "benchmark" was an interesting and potentially useful idea. To help spread the word about IUP, I think it could be useful to people to see a comparison of common basic GUI patterns written in different libraries.

Such a list would allow: - People to learn about libraries they may have not heard of before (IUP is relatively unknown compared to, say, Qt.) - See examples of code/how it is done. - Help those thinking about migrating from one library they currently know to a new one.

Anyway, I thought I would mention it in case anybody here would like to pick up the challenge and try writing an IUP version for those 7. Presumably and optionally, that page and examples could be forked to become a simple comparison page instead of focusing on the OO vs. functional thing.

Thanks, Eric

Challenge accepted, I am going to do Phix/pGUI.

Any other takers (eg EuGTK?)

Pete

new topic     » topic index » view message » categorize

2. Re: 7GUIs

That's a good idea - here's the first:

include GtkEngine.e 
 
integer ct = 0 
 
constant  
 win = create(GtkWindow,"size=150x50,border=10,$destroy=Quit"), 
 box = create(GtkBox,"homogeneous=TRUE"), 
 T = create(GtkEntry,"width-chars=10,text=0"), 
 B = create(GtkButton,"Count","CountUp") 
 add(box,{T,B}) 
 add(win,box) 
  
show_all(win) 
main() 
 
global function CountUp() 
 ct += 1 
 return set(T,"text",ct) 
end function 
new topic     » goto parent     » topic index » view message » categorize

3. Re: 7GUIs

Second:

include GtkEngine.e 
 
constant  
 win = create(GtkWindow,"size=150x50,border=10,$destroy=Quit"), 
 box = create(GtkBox,"orientation=HORIZONTAL,spacing=10"), 
 Tc = create(GtkEntry,"width-chars=10,$activate=ConvertTemp"), 
 Lc = create(GtkLabel,"text=Celsius ="), 
 Tf = create(GtkEntry,"width-chars=10,$activate=ConvertTemp"), 
 Lf = create(GtkLabel,"text=Fahrenheit") 
 
 add(box,{Tc,Lc,Tf,Lf}) 
 add(win,box) 
  
show_all(win) 
main() 
 
--------------------------------------- 
global function ConvertTemp(object ctl) 
--------------------------------------- 
object val = get(ctl,"text")  
if char_test(val,{{'0','9'}}) then 
 val = to_number(val) 
 switch ctl do 
   case Tf then set(Tc,"text",(val - 32) * (5/9)) 
   case else set(Tf,"text",val * (9/5) + 32) 
 end switch 
end if 
return 0 
end function 
new topic     » goto parent     » topic index » view message » categorize

4. Re: 7GUIs

Here's the third. Can someone suggest a better way of validating input dates? The rest require more work - not to write the code, but to understand the specs. Lunch takes priority!

Screenshots here: https://photos.app.goo.gl/EzuzcIIp8jCLusgn2

include GtkEngine.e 
include std/datetime.e 
 
constant css = create(GtkCssProvider,"GtkEntry#invalid {background: red;}") 
 
constant 
    win = create(GtkWindow,"size=150x-1,title=Book Flight,border=10,$destroy=Quit"), 
    pan = create(GtkBox,"orientation=VERTICAL,spacing=5") 
    gtk:add(win,pan) 
   
constant 
    opt = create(GtkComboBoxText) 
    gtk:add(opt,{"One-way flight","Return flight"}) 
    gtk:set(opt,"active",1) 
    connect(opt,"changed","UpdateT2") 
    gtk:add(pan,opt) 
 
constant  
    T1 = create(GtkEntry,"name=valid,text=01/1/2018,$activate=ValidDate"),  
    T2 = create(GtkEntry,"name=valid,text=01/01/2018,$activate=ValidDate,sensitive=FALSE"),  
    B1 = create(GtkButton,"Book","BookFlight") 
    gtk:add(pan,{T1,T2, B1})     
     
show_all(win)  
main() 
 
----------------------------------- 
global function ValidDate(atom ctl) 
----------------------------------- 
object d1 = get(ctl,"text") 
object d2 = retain_all("0123456789/",d1) 
object dt = -1 
 
if equal(d1,d2) then 
    dt = datetime:parse(d2,"%d/%m/%Y") 
end if 
 
if atom(dt) then 
    set(ctl,"name","invalid") 
    set(B1,"sensitive",FALSE) 
    return FALSE 
else 
    set(ctl,"name","valid") 
    set(B1,"sensitive",TRUE) 
end if 
 
 if get(opt,"active") = 2 then 
    set(B1,"sensitive",ValidDateRange()) 
 end if 
  
 return TRUE  
end function 
 
----------------------------------- 
global function ValidDateRange() 
----------------------------------- 
object dt1 = datetime:parse(get(T1,"text"),"%d/%m/%Y") 
object dt2 = datetime:parse(get(T2,"text"),"%d/%m/%Y") 
return datetime:diff(dt1,dt2) >= 0 
end function 
 
------------------------------ 
global function UpdateT2() 
------------------------------ 
  set(T2,"sensitive",get(opt,"active")-1)    
  return 1 
end function 
 
--------------------------------- 
global function BookFlight() 
--------------------------------- 
if ValidDate(T1) and ValidDate(T2) and ValidDateRange() then 
  switch get(opt,"active") do 
 
    case 1 then Info(win,"Congrats", 
        "You have booked a one-way flight", 
        sprintf("Leaving %s",{get(T1,"text")})) 
         
    case else Info(win,"Congrats","You have booked a round-trip flight", 
        sprintf("Leaving %s and returning %s",{get(T1,"text"),get(T2,"text")})) 
 
  end switch 
end if 
return 1 
end function 
new topic     » goto parent     » topic index » view message » categorize

5. Re: 7GUIs

irv said...

Can someone suggest a better way of validating input dates?

It's not too bad - the only one thing I might say is move the >=0 to inside ValidDateRange(). Here's what I did, using my own (decidedly Phix-only) timedate.e library:

include builtins\timedate.e 
set_timedate_formats({"DD.MM.YYYY"}) -- (add more if rqd) 
 
sequence d1 = parse_date_string(IupGetAttribute(T1,"VALUE")), 
         d2 = parse_date_string(IupGetAttribute(T2,"VALUE")) 
bool b1ok = timedate(d1), 
     b2ok = item=1 or (timedate(d2) and d2>=d1) 
    IupSetAttribute(T1,"BGCOLOR",iff(b1ok?"TXTBGCOLOR":"255 0 0")) 
    IupSetAttribute(T2,"BGCOLOR",iff(b2ok?"TXTBGCOLOR":"255 0 0")) 
    IupSetInt(T2,"ACTIVE",item=2) 
    IupSetInt(B,"ACTIVE",b1ok and b2ok) 

Just about got the Cells task working, now that was fun (some more cleanup/testing rqd).

Pete

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

6. Re: 7GUIs

Here's the timer:

include GtkEngine.e 
 
atom duration = 0, elapsed = 0 
 
constant  
    win = create(GtkWindow,"border=10,$destroy=Quit"), 
    grid = create(GtkGrid,"column spacing=10"), 
    L1 = create(GtkLabel,"Elapsed Time"), 
    G1 = create(GtkProgressBar), 
    L2 = create(GtkLabel,"0s"), 
    L3 = create(GtkLabel,"Duration"), 
    S1 = create(GtkScale,HORIZONTAL,0,60,.1), 
    B1 = create(GtkButton,"Reset","Reset") 
     
    add(win,grid) 
    --set(S1,"draw value",FALSE) 
    connect(S1,"value-changed","UpdateDuration") 
    set(grid,"attach",L1,1,1,1,1) 
    set(grid,"attach",G1,2,1,1,1) 
    set(grid,"attach",L2,1,2,1,1) 
    set(grid,"attach",L3,1,3,1,1) 
    set(grid,"attach",S1,2,3,1,1) 
    set(grid,"attach",B1,1,4,2,1) 
  
atom tick = create(GTimeout,100,_("tock")) 
 
show_all(win) 
main() 
 
----------------------- 
global function tock() 
----------------------- 
if duration <= 0 then return 1 end if 
 elapsed += 0.1 
 atom percent = round(elapsed/duration,10)  
 if duration >= elapsed and percent <= 100 then 
   set(G1,"fraction",percent) 
   set(L2,"text",text:format("[.1s]",elapsed)) 
 end if 
 return 1 
end function 
 
--------------------------------- 
global function UpdateDuration() 
--------------------------------- 
 duration = get(S1,"value") 
 return 1     
end function 
 
----------------------- 
global function Reset() 
----------------------- 
  elapsed = 0 
  set(G1,"fraction",0) 
    return 1 
end function 
new topic     » goto parent     » topic index » view message » categorize

7. Re: 7GUIs

all seven Phix/pGUI samples can now be found in demo\rosetta\7guis at https://bitbucket.org/petelomax/phix/src or try this direct link

Feedback welcome, especially regarding the "separation of concerns" aspect - as in how might one reorganise to best emulate it?

Pete

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

8. Re: 7GUIs

Here's crud (er.. the 5th challenge:)

 
include GtkEngine.e 
 
sequence names = { 
    "Emil, Hans", 
    "Mustermann, Max", 
    "Tisch, Roman" 
    } 
     
constant  
    win = create(GtkWindow,"size=200x200,border=10,$destroy=Quit"), 
    pan = create(GtkBox,"orientation=VERTICAL"), 
    grd = create(GtkGrid,"row spacing=5,column spacing=10,row homogeneous=TRUE"), 
    L1 = create(GtkLabel,"Filter prefix:"), 
    Tp = create(GtkEntry,"width-chars=10"), 
    Lx = create(GtkTreeView,"headers visible=FALSE"), 
    L2 = create(GtkLabel,"Name:"), 
    Tn = create(GtkEntry,"width-chars=10"), 
    L3 = create(GtkLabel,"Surname:"), 
    Ts = create(GtkEntry,"width-chars=10"), 
    BX = create(GtkButtonBox,"layout=2"), 
    Bc = create(GtkButton,"Create","AppendName"), 
    Bu = create(GtkButton,"Update","ReplaceName"), 
    Bd = create(GtkButton,"Delete","DeleteName") 
     
   add(win,pan) 
   pack_start(pan,grd,1,1) 
   add(BX,{Bc,Bu,Bd}) 
   set(grd,{ 
    {"attach",L1,1,1,1,1}, 
    {"attach",Tp,2,1,1,1}, 
    {"attach",Lx,1,2,2,5}, 
    {"attach",L2,3,2,1,1}, 
    {"attach",Tn,4,2,1,1}, 
    {"attach",L3,3,3,1,1}, 
    {"attach",Ts,4,3,1,1}, 
    {"attach",BX,1,7,3,1}}) 
   
constant buffer = get(Tp,"buffer") 
connect(buffer,"inserted-text","UpdateSearch") 
connect(buffer,"deleted-text","UpdateSearch") 
 
constant col1 = create(GtkColumn,"type=text,text=1") 
set(Lx,"append column",col1) 
 
object store = create(GtkListStore,{gSTR}) 
set(store,"data",names) 
set(Lx,"model",store) 
 
object selection = get(Lx,"selection") 
 
show_all(win) 
main() 
 
------------------------------ 
global function UpdateSearch() 
------------------------------ 
object data = FilterSurname(names) 
set(store,"clear") 
set(store,"data",data) 
return 1 
end function 
 
------------------------------------------- 
function FilterSurname(object x) 
------------------------------------------- 
object o = {} 
object p = upper(get(Tp,"text")) 
if length(p) = 0 then return names end if 
for i = 1 to length(x) do 
    if match(p,upper(x[i])) = 1 then o = append(o,x[i]) end if 
end for 
return o 
end function 
 
-------------------------- 
function input_name() 
-------------------------- 
return text:format("[], []",{get(Ts,"text"),get(Tn,"text")}) 
end function 
 
--------------------------------------------- 
global function AppendName() 
--------------------------------------------- 
object x = input_name() 
set(store,"append row",x) 
names = append(names,x)  
return 1 
end function 
 
-------------------------------------------- 
global function ReplaceName() 
-------------------------------------------- 
integer i = get(selection,"selected row") 
if i > 0 then 
    object x = input_name() 
    set(store,"replace row",{x},i) 
    i = match(x,names) 
    if i > 0 then 
        names[i] = x  
    end if 
end if 
return 1 
end function 
 
-------------------------------------------- 
global function DeleteName() 
-------------------------------------------- 
integer i = get(selection,"selected row") 
if i > 0 then 
    object x = get(selection,"selected row data") 
    set(store,"remove row",i)  
    names = remove_item(x[1],names)  
end if 
return 1 
end function 
 
new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu