implement Pimpl; include "mods.m"; mods, debug, win, tree: import dat; Cpointer, cols, panelback, maxpt, cookclick, drawtag, SET, CLEAR, HIGH, BORD, TEXT : import gui; Ptag, Predraw, Psync, Pdead, Pedit, Panel: import wpanel; panelctl, panelkbd, panelmouse, tagmouse, Tree: import wtree; Pgauge: adt { pcent: int; grect: Rect; }; panels: array of ref Pgauge; pimpl(p: ref Panel): ref Pgauge { if (p.implid < 0 || p.implid > len panels || panels[p.implid] == nil) panic("gauge: bug: no impl"); return panels[p.implid]; } init(d: Livedat): string { prefixes = list of {"gauge:", "slider:"}; dat = d; initmods(); return nil; } pinit(p: ref Panel) { if (tree == nil) tree = dat->tree; for (i := 0; i < len panels; i++) if (panels[i] == nil) break; if (i == len panels){ npanels := array[i+16] of ref Pgauge; npanels[0:] = panels; panels = npanels; } p.implid = i; panels[i] = ref Pgauge(50, Rect((0,0), (120, 20))); p.minsz = Point(120, 20); if (p.name[0:7] == "slider:") p.flags |= Pedit; } pterm(p: ref Panel) { if (p.implid != -1){ pimpl(p); # check panels[p.implid] = nil; p.implid = -1; } } pctl(p: ref Panel, s: string) { panelctl(tree, p, s); } pupdate(p: ref Panel, d: array of byte) { s := string d; pi := pimpl(p); if (pi == nil) return; npcent := int s; if (npcent > 100) npcent = 100; if (npcent < 0) npcent = 0; if (npcent != pi.pcent){ pi.pcent = npcent; p.flags |= Predraw; } } pevent(nil: ref Panel, nil: string) { # no events } pdraw(p: ref Panel) { pi := pimpl(p); if (pi == nil) return; set := p.rect; loff := set; loff.max.x = loff.min.x + 4; roff := set; roff.min.x = roff.max.x - 4; set.min.x += 4; set.max.x -= 4; if (p.rect.dy() > p.minsz.y){ dy := p.rect.dy() - p.minsz.y; set.min.y += dy/2; set.max.y -= dy/2; } clear := set; line := set; pi.grect = set; dx := int (set.dx() * pi.pcent / 100); clear.min.x = set.max.x = line.max.x = set.min.x + dx; line.min.x = line.max.x++ - 1; c := Point(line.min.x, (line.max.y+line.min.y)/2); cr := Rect((c.x-2, c.y-4), (c.x+4, c.y+4)); back := panelback(p); # draw back rects at left/right (to clear drag tag when 0%/100%) win.image.draw(loff, back, nil, (0,0)); win.image.draw(roff, back, nil, (0,0)); win.image.draw(set, cols[SET], nil, (0,0)); win.image.draw(clear, back, nil, (0,0)); win.image.draw(line, cols[BORD], nil, (0,0)); # draw drag tag only for sliders if (p.flags&Pedit) win.image.draw(cr, cols[BORD], nil, (0,0)); win.image.border(pi.grect, 1, cols[BORD], (0,0)); if (p.flags&Ptag) drawtag(p); } pmouse(p: ref Panel, m: ref Cpointer, mc: chan of ref Cpointer) { if (panelmouse(tree, p, m, mc)) return; pi := pimpl(p); if (pi == nil) return; oval := nval := pi.pcent; if ((p.flags&Pedit) && m.buttons == 1){ do { if (p.flags&Pdead) return; if (m.xy.x < pi.grect.min.x) m.xy.x = pi.grect.min.x; if (m.xy.x > pi.grect.max.x) m.xy.x = pi.grect.max.x; d := m.xy.sub(pi.grect.min); dx := pi.grect.dx(); nval = d.x * 100 / dx; if (nval != pi.pcent){ pi.pcent = nval; pdraw(p); } m = <-mc; } while(m.buttons&1); while(m.buttons != 0) m = <-mc; } if (nval != oval) p.flags |= Psync; } pkbd(p: ref Panel, r: int) { panelkbd(nil, p, r); } psync(p: ref Panel) { pi := pimpl(p); if (pi == nil) return; if (p.flags&Pedit){ fd := open(p.path + "/data", OWRITE|OTRUNC); if (fd == nil) return; fprint(fd, "%d\n", pi.pcent); } }