#include <u.h>
#include <libc.h>
#include <thread.h>
#include <fcall.h>
#include <draw.h>
#include <mouse.h>
#include <keyboard.h>
#include <9p.h>
#include <frame.h>
#include "gui.h"
#include "cook.h"
typedef struct DCol DCol;
struct DCol {
char* name;
int col;
Image* img;
};
static void xinit(Panel*);
static void xterm(Panel*);
static long xattrs(Panel* p, char* buf, long sz);
static long xread(Panel* p, void* buf, long cnt, vlong off);
static long xwrite(Panel* p, void* buf, long cnt, vlong off);
static void xmouse(Panel* p, Cmouse* m, Channel* mc);
static void xdraw(Panel*, int);
Pops drawops = {
.pref = "draw:",
.init = xinit,
.term = xterm,
.ctl = genctl,
.attrs= xattrs,
.read = xread,
.write= xwrite,
.draw = xdraw,
.mouse = xmouse,
.keyboard = genkeyboard,
};
DCol dcols[] = {
{"black", DBlack, nil},
{"white", CBack, nil},
{"grey", CClear, nil},
{"green", DGreen, nil},
{"red", DRed, nil},
{"blue", CSet, nil},
{"cyan", DCyan, nil},
{"magenta", DMagenta, nil},
{"yellow", DYellow, nil},
};
static void
allocdcols(void)
{
int i;
if (dcols[0].img != nil)
return;
for (i = 0; i < nelem(dcols); i++)
dcols[i].img = allocimage(display, Rect(0,0,1,1), RGB24, 1, dcols[i].col);
}
static void
xinit(Panel* p)
{
allocdcols();
p->minsz = Pt(48, 48);
p->flags |= Pedit;
p->irect = Rect(0, 0, p->minsz.x, p->minsz.y);
}
static void
xterm(Panel* p)
{
free(p->dcmds);
if (p->canvas)
freeimage(p->canvas);
}
static void
xdraw(Panel* p, int )
{
if (hidden(p->file) || Dx(p->rect) <= 0 || Dy(p->rect) <= 0)
return;
if (p->canvas && p->rect.max.x)
draw(screen, p->rect, p->canvas, nil, ZP);
if (p->flags&Ptag)
drawtag(p, 0);
}
static Point
atopt(char* s, char** ep)
{
char* e;
Point p;
p.x = strtod(s, &e);
p.y = strtod(e, &s);
*ep = s;
return p;
}
static Image*
atocol(char* s)
{
int i;
if (s && *s == ' ')
s++;
if (!s || !*s)
return nil;
for (i = 0; i < nelem(dcols); i++)
if (!strcmp(dcols[i].name, s))
return dcols[i].img;
return display->black;
}
static void
drawcmds(char* cmds, Image* canvas, Point* max)
{
char* s;
char* el;
Rectangle r;
Point pt;
Point rd;
Image* col;
int thick;
*max = ZP;
for(s = cmds; s && *s;){
el = strchr(s, '\n');
if (el)
*el++ = 0;
if (strncmp(s, "ellipse ", 8)== 0){
pt = atopt(s+7, &s);
rd = atopt(s, &s);
col = atocol(s);
if (max->x < pt.x + rd.x)
max->x = pt.x + rd.x;
if (max->y < pt.y + rd.y)
max->y = pt.y + rd.y;
if (canvas && col)
fillellipse(canvas, pt, rd.x, rd.y, col, ZP);
if (canvas && !col)
ellipse(canvas, pt, rd.x, rd.y, 0, cols[TEXT], ZP);
} else if (strncmp(s, "rect ", 5)== 0){
r.min = atopt(s+5, &s);
r.max = atopt(s, &s);
col = atocol(s);
if (max->x < r.max.x)
max->x = r.max.x;
if (max->y < r.max.y)
max->y = r.max.y;
if (canvas)
draw(canvas, r, col, nil, ZP);
} else if (strncmp(s, "line ", 5) == 0){
r.min = atopt(s+5, &s);
r.max = atopt(s, &s);
thick=strtod(s, &s);
col = atocol(s);
if (max->x < r.max.x)
max->x = r.max.x;
if (max->y < r.max.y)
max->y = r.max.y;
if (canvas)
line(canvas, r.min, r.max, 0, 0, thick, col, ZP);
} else if (strncmp(s, "poly ", 5) == 0){
abort(); // BUG: poligon(Pt,Pt,Pt....)
}
s = el;
if (el)
*--el = '\n';
}
max->x++;
max->y++;
if (max->x < 10)
max->x = 10;
if (max->y < 10)
max->y = 10;
}
static long
xattrs(Panel* p, char* str, long l)
{
char size[40];
seprint(size, size+sizeof(size),
"size %11d %11d\n", Dx(p->rect), Dy(p->rect));
return sprintattrs(p, str, l, size);
}
static long
xread(Panel* p, void* buf, long count, vlong off)
{
return genreadbuf(buf, count, off, p->dcmds, p->dsize);
}
static long
xwrite(Panel* p, void* buf, long cnt, vlong off)
{
Image* nimage;
Rectangle r;
Rectangle old;
Point max;
if (off + cnt + 1> p->dsize){
p->dcmds = erealloc9p(p->dcmds, off + cnt + 1);
p->dsize = off + cnt;
}
memmove(p->dcmds + off, buf, cnt);
p->dcmds[off + cnt] = 0;
if (p->size.x > 0){
p->dfile->length = strlen(p->dcmds);
drawcmds(p->dcmds, nil, &max);
r = Rpt(ZP, max);
nimage = allocimage(display, r, screen->chan, 0, CBack);
if (nimage == nil){
edprint("allocimage: %r\n");
return -1;
}
drawcmds(p->dcmds, nimage, &max);
p->minsz = max;
p->dloaded = 1;
old = Rpt(ZP, ZP);
if (p->canvas){
old = p->canvas->r;
freeimage(p->canvas);
}
p->canvas = nimage;
if (!hidden(p->file)){
if (eqrect(old, p->canvas->r)){
xdraw(p, 0);
flushimage(display, 1);
} else
resize();
}
}
return cnt;
}
static void
xmouse(Panel*p, Cmouse* m, Channel* mc)
{
Point pt;
int b;
pt = m->xy;
pt.x -= p->rect.min.x;
pt.y -= p->rect.min.y;
if ((b = m->buttons) && cookclick(m, mc))
event(p, "click %11d %11d %11d %11d", pt.x, pt.y, b, m->msec);
}
|