summaryrefslogtreecommitdiff
path: root/appl/wm/colors.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/wm/colors.b')
-rw-r--r--appl/wm/colors.b153
1 files changed, 153 insertions, 0 deletions
diff --git a/appl/wm/colors.b b/appl/wm/colors.b
new file mode 100644
index 00000000..619cffe0
--- /dev/null
+++ b/appl/wm/colors.b
@@ -0,0 +1,153 @@
+implement Colors;
+
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+ draw: Draw;
+ Display, Point, Rect, Image: import draw;
+include "tk.m";
+ tk: Tk;
+include "tkclient.m";
+ tkclient: Tkclient;
+
+Colors: module {
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+display: ref Display;
+top: ref Tk->Toplevel;
+tmpi: ref Image;
+
+task_cfg := array[] of {
+ "panel .c",
+ "label .l -anchor w -text {col:}",
+ "pack .l -fill x",
+ "pack .c -fill both -expand 1",
+ "bind .c <Button-1> {grab set .c; send cmd %X %Y}",
+ "bind .c <ButtonRelease-1> {grab release .c}",
+};
+
+init(ctxt: ref Draw->Context, nil: list of string)
+{
+ spawn init1(ctxt);
+}
+
+init1(ctxt: ref Draw->Context)
+{
+ sys = load Sys Sys->PATH;
+ draw = load Draw Draw->PATH;
+ tk = load Tk Tk->PATH;
+ tkclient = load Tkclient Tkclient->PATH;
+
+ tkclient->init();
+ display = ctxt.display;
+ tmpi = display.newimage(((0,0), (1, 1)), Draw->RGB24, 0, 0);
+
+ titlectl: chan of string;
+ (top, titlectl) = tkclient->toplevel(ctxt, "", "Colors", Tkclient->Appl);
+
+ cmdch := chan of string;
+ tk->namechan(top, cmdch, "cmd");
+
+ for (i := 0; i < len task_cfg; i++)
+ cmd(top, task_cfg[i]);
+ tk->putimage(top, ".c", cmap((256, 256)), nil);
+ cmd(top, "pack propagate . 0");
+ cmd(top, "update");
+ tkclient->onscreen(top, nil);
+ tkclient->startinput(top, "kbd"::"ptr"::nil);
+
+ for(;;) alt {
+ s := <-top.ctxt.kbd =>
+ tk->keyboard(top, s);
+ s := <-top.ctxt.ptr =>
+ tk->pointer(top, *s);
+ c := <-top.ctxt.ctl or
+ c = <-top.wreq or
+ c = <-titlectl =>
+ if(c == "exit")
+ return;
+ e := tkclient->wmctl(top, c);
+ if(e == nil && c[0] == '!'){
+ tk->putimage(top, ".c", cmap(actr(".c").size()), nil);
+ cmd(top, "update");
+ }
+
+ press := <-cmdch =>
+ (nil, toks) := sys->tokenize(press, " ");
+ color((int hd toks, int hd tl toks));
+ }
+}
+
+color(p: Point)
+{
+ r, g, b: int;
+ col: string;
+
+ cr := actr(".c");
+ if(p.in(cr)){
+ p = p.sub(cr.min);
+ p.x = (16*p.x)/cr.dx();
+ p.y = (16*p.y)/cr.dy();
+ (r, g, b) = display.cmap2rgb(16*p.y+p.x);
+ col = string (16*p.y+p.x);
+ }else{
+ tmpi.draw(tmpi.r, display.image, nil, p);
+ data := array[3] of byte;
+ ok := tmpi.readpixels(tmpi.r, data);
+ if(ok != len data)
+ return;
+ (r, g, b) = (int data[2], int data[1], int data[0]);
+ c := display.rgb2cmap(r, g, b);
+ (r1, g1, b1) := display.cmap2rgb(c);
+ if (r == r1 && g == g1 && b == b1)
+ col = string c;
+ else
+ col = "~" + string c;
+ }
+
+ cmd(top, ".l configure -text " +
+ sys->sprint("{col:%s #%.6X r%d g%d b%d}", col, (r<<16)|(g<<8)|b, r, g, b));
+ cmd(top, "update");
+}
+
+cmap(size: Point): ref Image
+{
+ # use writepixels because it's much faster than allocating all those colors.
+ img := display.newimage(((0, 0), size), Draw->CMAP8, 0, 0);
+ if (img == nil){
+ sys->print("colors: cannot make new image: %r\n");
+ return nil;
+ }
+
+ dy := (size.y / 16 + 1);
+ buf := array[size.x * dy] of byte;
+
+ for(y:=0; y<16; y++){
+ for (i := 0; i < size.x; i++)
+ buf[i] = byte (16*y + (16*i)/size.x);
+ for (i = 1; i < dy; i++)
+ buf[size.x*i:] = buf[0:size.x];
+ img.writepixels(((0, (y*size.y)/16), (size.x, ((y+1)*size.y) / 16)), buf);
+ }
+ return img;
+}
+
+actr(w: string): Rect
+{
+ r: Rect;
+ bd := int cmd(top, w + " cget -bd");
+ r.min.x = int cmd(top, w + " cget -actx") + bd;
+ r.min.y = int cmd(top, w + " cget -acty") + bd;
+ r.max.x = r.min.x + int cmd(top, w + " cget -actwidth");
+ r.max.y = r.min.y + int cmd(top, w + " cget -actheight");
+ return r;
+}
+
+cmd(top: ref Tk->Toplevel, cmd: string): string
+{
+ e := tk->cmd(top, cmd);
+ if (e != nil && e[0] == '!')
+ sys->print("colors: tk error on '%s': %s\n", cmd, e);
+ return e;
+}