implement Blurdemo; include "sys.m"; sys : Sys; include "draw.m"; draw: Draw; Display, Rect, Image: import draw; include "tk.m"; tk: Tk; include "tkclient.m"; tkclient: Tkclient; include "readdir.m"; readdir: Readdir; include "sh.m"; include "registries.m"; registries: Registries; Registry, Attributes, Service: import registries; include "grid/pathreader.m"; reader: PathReader; include "grid/browser.m"; browser: Browser; Browse, Select, File, Parameter, DESELECT, SELECT, TOGGLE: import browser; include "grid/srvbrowse.m"; srvbrowse: Srvbrowse; include "grid/announce.m"; announce: Announce; include "grid/readjpg.m"; readjpg: Readjpg; srvfilter: list of list of (string, string); currstep: int; currsrv: ref Service; currattach: ref Registries->Attached; ctxt: ref Draw->Context; display: ref Draw->Display; sysname : string; IMAGE: con 0; MOUNT: con 4; imgcache: ref Image; br: ref Browse; sel: ref Select; Blurdemo : module { init : fn (context : ref Draw->Context, argv : list of string); readpath: fn (dir: File): (array of ref sys->Dir, int); }; init(context : ref Draw->Context, argv: list of string) { ctxt = context; display = ctxt.display; sys = load Sys Sys->PATH; if (sys == nil) badmod(Sys->PATH); readdir = load Readdir Readdir->PATH; if (readdir == nil) badmod(Readdir->PATH); draw = load Draw Draw->PATH; if (draw == nil) badmod(Draw->PATH); tk = load Tk Tk->PATH; if (tk == nil) badmod(Tk->PATH); tkclient = load Tkclient Tkclient->PATH; if (tkclient == nil) badmod(Tkclient->PATH); tkclient->init(); registries = load Registries Registries->PATH; if (registries == nil) badmod(Registries->PATH); registries->init(); browser = load Browser Browser->PATH; if (browser == nil) badmod(Browser->PATH); browser->init(); srvbrowse = load Srvbrowse Srvbrowse->PATH; if (srvbrowse == nil) badmod(Srvbrowse->PATH); srvbrowse->init(); announce = load Announce Announce->PATH; if (announce == nil) badmod(Announce->PATH); announce->init(); reader = load PathReader "$self"; if (reader == nil) badmod("PathReader"); readjpg = load Readjpg Readjpg->PATH; if (readjpg == nil) badmod(Readjpg->PATH); readjpg->init(display); sys->pctl(sys->FORKNS | sys->NEWPGRP, nil); if (ctxt == nil) { sys->print("no draw context found!\n"); exit; } sysname = readfile("/dev/sysname"); if (sysname == "") sysname = "Localhost"; imgcache = nil; setsrvfilter(); root := "/"; currsrv = nil; attribs := ("resource", "Cpu Pool") :: nil; lcpupool := srvbrowse->find(attribs :: nil); if (lcpupool == nil) { browser->dialog(ctxt, nil, "ok" :: nil, "Alert","Cannot find a Cpu Pool Resource"); raise "fail: error cannot find a Cpu Pool resource"; } (top, titlebar) := tkclient->toplevel(ctxt,"","BlurDemo", tkclient->Appl); butchan := chan of string; tk->namechan(top, butchan, "butchan"); browsechan := chan of string; tk->namechan(top, browsechan, "browsechan"); selectchan := chan of string; tk->namechan(top, selectchan, "selectchan"); br = Browse.new(top, "browsechan", "services/", "Services", 1, reader); bropened := array[] of { "services/", "services/Data source/", "services/Camera/", "/n/remote/", "/" , }; for (i := 0; i < len bropened; i++) br.addopened(File (bropened[i], nil), 1); sel = Select.new(top, "selectchan"); for (ik := 0; ik < len mainscreen; ik++) tkcmd(top,mainscreen[ik]); currstep = -1; sel.addframe("image", "Select a '.bit' image"); changestep(top, IMAGE, nil); tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0"); released := 1; title := ""; resize(top, ref Rect ((0,0), (400,400))); tkclient->onscreen(top, nil); tkclient->startinput(top, "kbd"::"ptr"::nil); tkpath: string; selected := array[2] of File; if (tl argv != nil) spawn initimg(butchan, hd tl argv); main: for (;;) { alt { s := <-top.ctxt.kbd => tk->keyboard(top, s); s := <-top.ctxt.ptr => tk->pointer(top, *s); inp := <-browsechan => (nil, lst) := sys->tokenize(inp, " \n\t"); if (len lst > 1) tkpath = hd tl lst; selected[0] = br.getselected(0); selected[1] = br.getselected(1); br.defaultaction(lst, nil); i = -1; if (!File.eq(selected[0], br.getselected(0))) i = 0; if (!File.eq(selected[1], br.getselected(1))) i = 1; if (i != -1) { sel.select(sel.currfname,nil,DESELECT); actionbutton(top, br.selected[i].file.path, br.selected[i].tkpath); } tkcmd(top, "update"); inp := <-selectchan => (nil, lst) := sys->tokenize(inp, " \n\t"); case hd lst { "but3" => tkpath = hd tl lst; x := string (int hd tl tl lst - 5); y := string (int hd tl tl tl lst - 5); path := tkcmd(top, tkpath+" cget -text"); s := blursrvc.attrs.get("name") + " ("+blursrvc.addr+")"; tk->cmd(top, "destroy .m2"); tkcmd(top, "menu .m2 -font /fonts/charon/plain.normal.font"); tkcmd(top, ".m2 add command -label {"+path+"}"); tkcmd(top, ".m2 add separator"); tkcmd(top, ".m2 add command -label {"+s+"}"); tkcmd(top, ".m2 post "+x+" "+y); "double1" => tkpath = hd tl lst; path := tkcmd(top, tkpath+" cget -text"); qid := ""; (n, nil) := sys->tokenize(path, "/"); if (currstep == IMAGE) { qid = srvbrowse->getqid(blursrvc); (res,name) := srvbrowse->getresname(blursrvc); path = "services/"+res+"/"+name+"/"; } else if (currsrv.addr != blursrvc.addr) break; else if (blursrvc.addr != "Local Machine") path = "/n/remote" + path; tkpath = br.gotoselectfile(File(path,qid)); if (tkpath != nil) { sel.select(sel.currfname, nil, DESELECT); actionbutton(top, path, tkpath); } "but1" => if (currstep == IMAGE) br.selectfile(0, DESELECT, File (nil, nil), nil); else br.selectfile(1, DESELECT, File (nil, nil), nil); sel.defaultaction(lst); actionbutton(top, sel.getselected(sel.currfname), hd tl lst); * => sel.defaultaction(lst); } tkcmd(top, "update"); inp := <-butchan => # sys->print("inp: %s\n",inp); (nil, lst) := sys->tokenize(inp, " \n\t"); if (len lst > 1) tkpath = hd tl lst; case hd lst { "refresh" => # ! check to see if anything is mounted first if (currstep == IMAGE) { # addlocalservice(); srvbrowse->refreshservices(srvfilter); } br.refresh(); "back" => changestep(top, IMAGE, nil); "run" => spawn run(ctxt, getcoords(top)); "preview" => spawn previewwin(top, butchan, hd tl lst); "add" => additem(top, hd tl lst, int hd tl tl lst); "del" => sel.delselection("image", hd tl lst); tkcmd (top, ".f.ftop.bn configure -state disabled"); blurimage = nil; blurtkpath = nil; blursrvc = nil; actionbutton(top, sel.getselected(sel.currfname), hd tl lst); "mount" => file := br.getpath(tkpath); (nsrv, lsrv) := sys->tokenize(file.path, "/"); if (currstep != IMAGE) break; if (nsrv != 3) break; if (hd tl tl lsrv != "Local Filestore") { ok := mountsrv(file.path, file.qid, getcoords(top)); if (!ok) break; changestep(top, MOUNT, hd tl tl lsrv); } else { srv : Service; srv.attrs = Attributes.new(("name", sysname) :: nil); srv.addr = "Local Machine"; currsrv = ref srv; changestep(top, MOUNT, hd tl tl lsrv); } } tkcmd(top, "update"); title = <-top.ctxt.ctl or title = <-top.wreq or title = <-titlebar => if (title == "exit") break main; e := tkclient->wmctl(top, title); if (e == nil && title[0] == '!') { (nil, lst) := sys->tokenize(title, " \t\n"); if (len lst >= 2 && hd lst == "!size" && hd tl lst == ".") resize(top, nil); } } } currattach = nil; killg(sys->pctl(0,nil)); } resize(top: ref Tk->Toplevel, r: ref Draw->Rect) { if (r != nil) { sw := (*r).dx(); sh := (*r).dy(); ww := int tkcmd(top, ". cget -actwidth"); wh := int tkcmd(top, ". cget -actheight"); if (ww > sw) tkcmd(top, ". configure -x 0 -width "+string sw); if (wh > sh) tkcmd(top, ". configure -y 0 -height "+string sh); } w := int tkcmd(top, ".fselect cget -actwidth"); h := int tkcmd(top, ".fselect cget -actheight"); sel.resize(w,h); } nactionbuttons := 0; actionbutton(top: ref Tk->Toplevel, path, tkpath: string) { for (i := 0; i < nactionbuttons; i++) { tkcmd(top, "grid forget .f.ftop.baction"+string i); tkcmd(top, "destroy .f.ftop.baction"+string i); } if (path == nil) { nactionbuttons = 0; return; } buttons : list of (string,string) = nil; (n, nil) := sys->tokenize(path, "/"); if (len tkpath > 8 && tkpath[:8] == ".fselect") buttons = ("Remove", "del "+tkpath) :: buttons; else { if (currstep == IMAGE) { if (n == 3) buttons = ("Mount", "mount "+tkpath) :: buttons; } else { if (len path > 4) { if (path[len path - 4:] == ".bit") { buttons = ("Select", "add "+path+" 0") :: ("Preview", "preview "+path) :: buttons; } else if (path[len path - 4:] == ".jpg") buttons = ("Select", "add "+path+" 0") :: buttons; } } } nactionbuttons = len buttons; for (i = 0; i < nactionbuttons; i++) { name := ".f.ftop.baction"+string i+" "; (text,cmd) := hd buttons; tkcmd(top, "button "+name+"-text {"+text+"} "+ "-font /fonts/charon/bold.normal.font "+ "-command {send butchan "+cmd+"}"); tkcmd(top, "grid "+name+" -row 0 -column "+string (4+i)); buttons = tl buttons; } } initimg(butchan: chan of string, imgpath: string) { srv : Service; srv.attrs = Attributes.new(("name", sysname) :: nil); srv.addr = "Local Machine"; currsrv = ref srv; butchan <-= "add "+imgpath+" 0"; butchan <-= "back"; } blurimage := ""; blurtkpath := ""; blursrvc: ref Service; additem(top: ref Tk->Toplevel, path: string, overwrite: int) { if (blurimage != nil) { if (overwrite || browser->dialog(ctxt, top, "ok" :: "cancel" :: nil, "Alert","Replace existing image '" +nopath(blurimage)+"' with '"+nopath(path)+"'?") == 0) { sel.delselection("image", blurtkpath); } else return; } imgpath := path; if (currsrv.addr != "Local Machine") path = path[len "/n/remote":]; blurtkpath = sel.addselection("image", path, nil, 0); tkcmd(top, "update"); blurimage = path; blursrvc = currsrv; if (overwrite) spawn getpreview(blurtkpath, nil, imgcache); else spawn getpreview(blurtkpath, imgpath, nil); } nopath(file: string): string { return file[len browser->prevpath(file):]; } runscr := array[] of { "frame .f", "frame .f.f1", "label .f.f1.l -text {Select no of CPUs} -font /fonts/charon/plain.normal.font", "scale .f.f1.s -orient horizontal -height 16 -showvalue 0 -from 1 -to 20 -command {.f.f1.ls configure -text}", "label .f.f1.ls -text {1} -font /fonts/charon/plain.normal.font -width 30", "button .f.f1.b -text {Run} -font /fonts/charon/plain.normal.font -command {send butchan go}", "pack .f.f1.l .f.f1.s .f.f1.ls .f.f1.b -side left", "frame .f.f2", "text .f.f2.t -width 250 -height 150 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font -yscrollcommand { .f.f2.sy set }", "scrollbar .f.f2.sy -command { .f.f2.t yview }", "pack .f.f2.sy -side left -fill y", "pack .f.f2.t -fill both -expand 1", "bind .Wm_t +{focus .Wm_t}", "bind .Wm_t.title +{focus .Wm_t}", "focus .Wm_t", "pack .f.f1 -side top", "pack .f.f2 -fill both -expand 1", }; run(ctxt: ref Draw->Context, coords: draw->Rect) { (top, titlectl) := tkclient->toplevel(ctxt, "", nil, tkclient->Resize); butchan := chan of string; sync := chan of int; quit := chan of int; tk->namechan(top, butchan, "butchan"); tkcmds(top, runscr); tkcmd(top, ". configure "+getcentre(top, coords)); tkcmd(top, "pack .f -fill both -expand 1; pack propagate . 0; focus .; update"); tkclient->onscreen(top, "exact"); tkclient->startinput(top, "kbd"::"ptr"::nil); done := 1; loop: for (;;) { alt { s := <-top.ctxt.kbd => tk->keyboard(top, s); s := <-top.ctxt.ptr => tk->pointer(top, *s); <-sync => tkcmd(top, ".f.f1.b configure -state normal; update"); done = 1; inp := <-butchan => (nil, lst) := sys->tokenize(inp, " \n\t"); case hd lst { "go" => tkcmd(top, ".f.f1.b configure -state disabled"); ncpus := int tkcmd(top, ".f.f1.s get"); done = 0; spawn startit(ncpus, butchan, sync, quit); "output" => tkcmd(top, ".f.f2.t insert end {"+inp[len "output ":]+"}"); "error" => tkcmd(top, ".f.f2.t insert end {Error: "+inp[len "error ":]+"\n}"); tkcmd(top, ".f.f1.b configure -state normal"); "fewcpu" => i := browser->dialog(ctxt, top, "ok" :: "cancel" :: nil, "Alert", "Only found "+hd tl lst+" cpus available. Continue?"); quit <-= i; if (i == 1) return; } tkcmd(top, "update"); s := <-top.ctxt.ctl or s = <-top.wreq or s = <- titlectl => if (s == "exit") { if (done) return; break loop; } else tkclient->wmctl(top, s); } } top = nil; for (;;) alt { <- butchan => ; <-sync => return; } } startit(ncpus: int, butchan: chan of string, sync, quit: chan of int) { imgattached : ref Registries->Attached; imgpath := blurimage; if (blursrvc.addr != "Local Machine") { imgattached = blursrvc.attach(nil, nil); if (imgattached == nil) { butchan <-= "error cannot connect to data source: "+blursrvc.attrs.get("name"); return; } if (sys->mount(imgattached.fd, nil, "/n/local", sys->MREPL, nil) == -1) { butchan <-= sys->sprint("error img mount failed: %r"); return; } imgpath = "/n/local" + imgpath; butchan <-= "output Found image namespace\n"; } sys->pctl(sys->FORKNS, nil); attribs := ("resource", "Cpu Pool") :: nil; lsrv := srvbrowse->find(attribs :: nil); if (lsrv == nil) { butchan <-= "error cannot find Cpu Pool resource"; return; } cpupoolsrvc := hd lsrv; attached := cpupoolsrvc.attach(nil, nil); if (attached == nil) { butchan <-= "error cannot connect to Cpu Pool resource"; return; } if (sys->mount(attached.fd, nil, "/n/remote", sys->MREPL, nil) == -1) { butchan <-= sys->sprint("error Cpu Pool mount failed: %r"); return; } butchan <-= "output Connected to Cpu Pool resource\n"; if (blurimage[len blurimage - 4:] == ".jpg") { butchan <-= "output Converting jpg => bit image\n"; chanin := chan of string; killchan := chan of int; spawn jpgprog(butchan, chanin, killchan); img := readjpg->jpg2img(imgpath, "", chan of string, chanin); killchan <-= 1; butchan <-= "output \n"; if (img == nil) { butchan <-= "error Error converting jpg"; return; } sys->remove("/n/remote/data/blurimage.bit"); fd := sys->create("/n/remote/data/blurimage.bit", sys->OWRITE, 8r666); if (fd == nil || display.writeimage(fd, img) == -1) { butchan <-= sys->sprint("error Error saving bit: %r"); return; } imgpath = "/n/remote/data/blurimage.bit"; } afd := array[ncpus] of ref sys->FD; ngot := 0; for (i := 0; i < ncpus; i++) { afd[ngot] = sys->open("/n/remote/clone", sys->ORDWR); if (afd[ngot] == nil) break; ngot++; } if (ngot == 0) { butchan <-= "error no cpu resources available"; return; } if (ngot < ncpus) { butchan <-= "fewcpu "+string ngot; q := <-quit; if (q) return; } butchan <-= "output Found "+string ngot+" Cpu resource(s)\n"; sh := load Sh Sh->PATH; if (sh == nil) badmod(Sh->PATH); sys->create("/n/remote/data/blur", sys->OREAD, 8r777 | sys->DMDIR); done := chan of int; for (i = 0; i < ngot; i++) spawn go(afd[i], i, butchan, done); err := sh->run(ctxt, "/dis/grid/demo/blur.dis" :: "/n/remote/data" :: imgpath :: nil); if (err != nil) butchan <-= "error "+err; finished := 0; for (;;) { <-done; finished++; if (finished == ngot) break; } sys->unmount(nil, "/n/remote"); butchan <-= "output Finished\n"; sync <-= 1; } jpgprog(butchan, chanin: chan of string, killchan: chan of int) { i := 0; for (;;) alt { <-killchan => return; <-chanin => i = (i+1) % 2; if (i) butchan <-= "output ."; } } go(fd: ref sys->FD, id: int, butchan: chan of string, done: chan of int) { op := "output Cpu "+string id+": "; sys->fprint(fd, "/dis/grid/demo/blur.dis /data/"); buf := array[sys->ATOMICIO] of byte; sys->seek(fd, big 0, sys->SEEKSTART); i := sys->read(fd, buf, len buf); if (i < 1) sys->print("Error reading dir name: %r\n"); dir := string buf[:i]; if (dir[len dir - 1] == '\n') dir = dir[:len dir -1]; fdout := sys->open("/n/remote/"+dir+"/data", sys->OREAD); if (fdout == nil) { butchan <-= op+"Cannot read from stdout"; done <-= 1; return; } for (;;) { i = sys->read(fdout, buf, len buf); if (i < 1) break; s := string buf[:i]; if (s[len s - 1] != '\n') s[len s] = '\n'; butchan <-= op+s; } done <-= 1; } kill(pid: int) { if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil) sys->fprint(fd, "kill"); } killg(pid: int) { if ((fd := sys->open("/prog/" + string pid + "/ctl", Sys->OWRITE)) != nil) sys->fprint(fd, "killgrp"); } mainscreen := array[] of { "frame .f", "frame .f.ftop", "variable opt command", "button .f.ftop.bp -text {Services} -command {send butchan back} -font /fonts/charon/bold.normal.font -state disabled -state disabled", "button .f.ftop.bn -text {Run} -command {send butchan run} -font /fonts/charon/bold.normal.font -state disabled", "button .f.ftop.br -text {Refresh} -command {send butchan refresh} -font /fonts/charon/bold.normal.font", "grid .f.ftop.br .f.ftop.bp .f.ftop.bn -row 0", "grid columnconfigure .f.ftop 3 -minsize 30", "label .f.l -text { } -height 1 -bg red", "grid .f.l -row 1 -column 0 -sticky ew", "grid .f.ftop -row 0 -column 0 -pady 2 -sticky w", "grid .fbrowse -in .f -row 2 -column 0 -sticky nsew", "grid .fselect -in .f -row 3 -column 0 -sticky nsew", "grid columnconfigure .f 0 -weight 1", "grid rowconfigure .f 2 -weight 1", "grid rowconfigure .f 3 -weight 1", "bind .Wm_t +{focus .Wm_t}", "bind .Wm_t.title +{focus .Wm_t}", "focus .Wm_t", }; readpath(dir: File): (array of ref sys->Dir, int) { if (currstep == MOUNT) { (dirs, nil) := readdir->init(dir.path, readdir->NAME | readdir->COMPACT); dirs2 := array[len dirs] of ref sys->Dir; num := 0; for (i := 0; i < len dirs; i++) if (dirs[i].mode & sys->DMDIR || (len dirs[i].name > 4 && ( dirs[i].name[len dirs[i].name - 4:] == ".bit" || dirs[i].name[len dirs[i].name - 4:] == ".jpg"))) dirs2[num++] = dirs[i]; return (dirs2[:num], 0); } else return srvbrowse->servicepath2Dir(dir.path, int dir.qid); return (nil, 0); } badmod(path: string) { sys->print("Blurdemo: failed to load %s: %r\n",path); exit; } mountscr := array[] of { "frame .f -borderwidth 2 -relief raised", "text .f.t -width 200 -height 60 -borderwidth 1 -bg white -font /fonts/charon/plain.normal.font", "button .f.b -text {Cancel} -command {send butchan cancel} -width 70 -font /fonts/charon/plain.normal.font", "grid .f.t -row 0 -column 0 -padx 10 -pady 10", "grid .f.b -row 1 -column 0 -sticky n", "grid rowconfigure .f 1 -minsize 30", }; mountsrv(srvpath, qid: string, coords: draw->Rect):int { (top, nil) := tkclient->toplevel(ctxt, "", nil, tkclient->Plain); ctlchan := chan of string; butchan := chan of string; tk->namechan(top, butchan, "butchan"); tkcmds(top, mountscr); tkcmd(top, ". configure "+getcentre(top, coords)+"; pack .f; update"); spawn mountit(srvpath, qid, ctlchan); pid := int <-ctlchan; tkclient->onscreen(top, "exact"); tkclient->startinput(top, "kbd"::"ptr"::nil); for (;;) { alt { s := <-top.ctxt.kbd => tk->keyboard(top, s); s := <-top.ctxt.ptr => tk->pointer(top, *s); e := <- ctlchan => if (e[0] == '!') { tkcmd(top, ".f.t insert end {"+e[1:]+"}"); tkcmd(top, ".f.b configure -text {close}; update"); pid = -1; } else if (e == "ok") return 1; else tkcmd(top, ".f.t insert end {"+e+"}; update"); <- butchan => if (pid != -1) kill(pid); return 0; } } return 0; } mountit(srvpath, qid: string, ctlchan: chan of string) { ctlchan <-= string sys->pctl(0,nil); n := 0; (nil, lst) := sys->tokenize(srvpath, "/"); stype := hd tl lst; name := hd tl tl lst; addr := ""; ctlchan <-= "Connecting...\n"; lsrv := srvbrowse->servicepath2Service(srvpath, qid); if (len lsrv < 1) { ctlchan <-= "!could not find service"; return; } srvc := hd lsrv; currattach = srvc.attach(nil, nil); if (currattach == nil) { ctlchan <-= "!attach failed"; return; } ctlchan <-= "Mounting...\n"; if (sys->mount(currattach.fd, nil, "/n/remote", sys->MREPL, nil) != -1) { ctlchan <-= "ok"; currsrv = srvc; } else ctlchan <-= "!mount failed"; } getcoords(top: ref Tk->Toplevel): draw->Rect { h := int tkcmd(top, ". cget -height"); w := int tkcmd(top, ". cget -width"); x := int tkcmd(top, ". cget -actx"); y := int tkcmd(top, ". cget -acty"); r := draw->Rect((x,y),(x+w,y+h)); return r; } getcentre(top: ref Tk->Toplevel, winr: draw->Rect): string { h := int tkcmd(top, ".f cget -height"); w := int tkcmd(top, ".f cget -width"); midx := winr.min.x + (winr.dx() / 2); midy := winr.min.y + (winr.dy() / 2); newx := midx - (w/2); newy := midy - (h/2); return "-x "+string newx+" -y "+string newy; } changestep(top: ref Tk->Toplevel, step: int, label: string) { root, rlabel: string; if (step == MOUNT) { tkcmd (top, ".f.ftop.bp configure -state normal"); br.changeview(2); rlabel = label; if (currsrv.addr == "Local Machine") root = "/"; else root = "/n/remote/"; } else if (step == IMAGE) { br.changeview(1); if (currsrv != nil) { sys->unmount(nil, "/n/remote"); currattach = nil; currsrv = nil; } srvbrowse->refreshservices(srvfilter); root = "services/"; rlabel = "Image Services"; sel.showframe("image"); tkcmd (top, ".f.ftop.bp configure -state disabled"); # addlocalservice(); sel.select("image", nil, DESELECT); } currstep = step; br.selectfile(1, DESELECT, File (nil, nil), nil); br.selectfile(0, DESELECT,File (nil, nil), nil); actionbutton(top, nil, nil); br.newroot(root, rlabel); if (currstep == MOUNT) br.selectfile(0, SELECT, File (root, nil), ".fbrowse.fl.f0.l"); tkcmd(top, "update"); } addlocalservice() { lsrv : Service; attrs := ("resource", "Data source") :: ("name", "Local Filestore") :: ("type", "styx") :: nil; lsrv.attrs = Attributes.new(attrs); lsrv.addr = "@your local filestore"; srvbrowse->addservice(ref lsrv); } tkcmd(top: ref Tk->Toplevel, cmd: string): string { e := tk->cmd(top, cmd); if (e != "" && e[0] == '!') sys->print("Tk error: '%s': %s\n",cmd,e); return e; } tkcmds(top: ref Tk->Toplevel, a: array of string) { for (j := 0; j < len a; j++) tkcmd(top, a[j]); } readfile(f: string): string { fd := sys->open(f, sys->OREAD); if(fd == nil) return nil; buf := array[8192] of byte; n := sys->read(fd, buf, len buf); if(n < 0) return nil; return string buf[:n]; } setsrvfilter() { imagefilter := ("proto", "styx") :: ("auth", "none") :: ("Image resource", "1") :: nil; srvfilter = imagefilter :: nil; } getpreview(tkpath, imgpath: string, img: ref Image) { if (imgpath != nil && imgpath[len imgpath - 4:] == ".jpg") { tkcmd (sel.top, ".f.ftop.bn configure -state normal"); return; } if (img == nil) { img = display.open(imgpath); if (img == nil) { browser->dialog(ctxt, sel.top, "ok" :: nil, "Alert", sys->sprint("Invalid '.bit' image: %r")); sel.delselection("image", blurtkpath); blurimage = nil; blursrvc = nil; return; } } previmg := preview(img, 100); tk->cmd(sel.top, "destroy .preview"); tkcmd(sel.top, "image create bitmap .preview"); tk->putimage(sel.top, ".preview", previmg, nil); tkcmd(sel.top, sys->sprint("%s configure -image .preview -width %d -height %d", tkpath, previmg.r.dx(), previmg.r.dy())); tkcmd(sel.top, "grid forget "+tkpath+"; grid "+tkpath+" -row 1 "+ "-column 0 -columnspan 3 -pady 5 -sticky ew;"); sel.setscrollr(sel.currfname); tkcmd (sel.top, ".f.ftop.bn configure -state normal"); tkcmd(sel.top, "update;"); } preview(img: ref Image, maxsize: int): ref Image { mx := max(img.r.dx(), img.r.dy()); if (mx <= maxsize) { imgcache = img; return img; } prevr := Rect ((0,0), (img.r.dx()*maxsize/mx, img.r.dy()*maxsize/mx)); tmpimg := display.newimage(img.r, Draw->RGB24, 0, Draw->White); previmg := display.newimage(prevr, Draw->RGB24, 0, Draw->White); tmpimg.draw(img.r, img, nil, (0,0)); getr := Rect ((0,0), (img.r.dx() / prevr.dx(), img.r.dy() / prevr.dy())); nopixels := getr.dx() * getr.dy(); getrgb := array[nopixels * 3] of byte; newrgb := array[3] of byte; for (y := 0; y < prevr.dy(); y++) { for (x := 0; x < prevr.dx(); x++) { tmpimg.readpixels(getr.addpt((x*getr.dx(), y*getr.dy())), getrgb); tmprgb := array[] of { 0, 0, 0 }; for (i := 0; i < len getrgb; i++) tmprgb[i%3] += int getrgb[i]; for (i = 0; i < 3; i++) newrgb[i] = byte (tmprgb[i] / nopixels); previmg.writepixels(((x,y),(x+1,y+1)), newrgb); } } imgcache = previmg; return previmg; } max(a,b: int): int { if (a > b) return a; return b; } previewscr := array[] of { "frame .f", "panel .f.p -borderwidth 2 -relief raised", "button .f.bs -text Select -font /fonts/charon/plain.normal.font -command {send prevchan select} -state disabled", "button .f.bc -text Close -font /fonts/charon/plain.normal.font -command {send prevchan close} -state disabled", "pack .f", "grid .f.p -row 0 -column 0 -columnspan 2 -padx 5 -pady 5", "grid .f.bs .f.bc -row 1 -padx 5 -pady 5", "update", }; previewwin(oldtop: ref Tk->Toplevel, chanout: chan of string, path: string) { (top, titlectl) := tkclient->toplevel(ctxt, "", "Loading...", 0); prevchan := chan of string; tk->namechan(top, prevchan, "prevchan"); tkclient->onscreen(top, "exact"); img := display.open(path); if (img == nil) { browser->dialog(ctxt, oldtop, "ok" :: nil, "Alert", "Invalid '.bit' image"); return; } previmg := preview(img, 100); tkcmds(top, previewscr); tk->putimage(top, ".f.p", previmg, nil); tkcmd(top, ".Wm_t.title configure -text Preview"); tkcmd(top, ".f.p dirty; update"); browser->setcentre(oldtop, top); tkcmd(top, ".f.bs configure -state normal; .f.bc configure -state normal"); tkclient->startinput(top, "kbd"::"ptr"::nil); main: for(;;) alt { s := <-top.ctxt.kbd => tk->keyboard(top, s); s := <-top.ctxt.ptr => tk->pointer(top, *s); s := <- prevchan => if (s == "select") chanout <-= "add "+path+" 1"; break main; s := <-top.ctxt.ctl or s = <-top.wreq or s = <- titlectl => if (s == "exit") break main; else tkclient->wmctl(top, s); } }