ref: 426d4a16d137b3a6612a336c0f1259ad5c488ad1
dir: /map.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
#include <keyboard.h>
#include <nate/nate.h>
#include <nate/n_window.h>
#include <nate/n_hbox.h>
#include <nate/n_vbox.h>
#include <nate/n_box.h>
#include <nate/n_label.h>
#include <nate/n_button.h>
#include <nate/n_image.h>
#include "dat.h"
#include "fns.h"
void
debugprint(char *fmt, ...)
{
va_list args;
if (!debug)
return;
va_start(args, fmt);
vfprint(2, fmt, args);
va_end(args);
}
static void
runchecks(void)
{
if (access("/mnt/map/0", AEXIST) < 0)
sysfatal("/mnt/map does not exist: %r");
}
NWindow *mainwindow;
NImage *nimage;
enum {
Cnil,
Credraw,
};
GPos gpsloc;
GBundle currentloc;
Point drawoffset;
int maxzoom = 8;
int zoom = 5;
int tilesize = 256;
Image *mapimage;
QLock mapimagelock;
void
lockmapimage(void)
{
qlock(&mapimagelock);
}
void
unlockmapimage(void)
{
qunlock(&mapimagelock);
}
int debug;
int shouldredraw = 0;
QLock shouldredrawl;
/* main thread */
void
checkcondredraw(void)
{
int b;
qlock(&shouldredrawl);
b = shouldredraw;
shouldredraw = 0;
qunlock(&shouldredrawl);
if (!b)
return;
nateredraw(0);
}
/* download threads */
void
imageupdated(void)
{
qlock(&shouldredrawl);
shouldredraw++;
qunlock(&shouldredrawl);
}
void
redrawmap(void)
{
requestimage(currentloc, imageupdated);
}
void
initimage(void)
{
Rectangle r;
if (mapimage) {
freeimage(mapimage);
mapimage = nil;
}
ncallcalcrect(mainwindow, screen, screen->r);
r.max.x = Dx(nimage->slot.r);
r.max.y = Dy(nimage->slot.r);
mapimage = allocimage(display, r, screen->chan, 0, DWhite);
nimage->image = mapimage;
}
void
eresized(int new)
{
Point isize;
if (new && getwindow(display, Refnone) < 0)
sysfatal("%r");
freeimage(mapimage);
nimage->image = nil;
ncallcalcrect(mainwindow, screen, screen->r);
isize.x = Dx(nimage->slot.r);
isize.y = Dy(nimage->slot.r);
debugprint("resized image: %P\n", isize);
mapimage = allocimage(display, Rect(0, 0, isize.x, isize.y), screen->chan, 0, DWhite);
nimage->image = mapimage;
redrawmap();
nateredraw(0);
}
int
exitclicked(Mouse, Nelem *, void*)
{
exits(nil);
}
static void
traperrout(void)
{
int p[2];
pipe(p);
dup(p[0], 2);
int fd = create("/srv/map.errout", OWRITE|ORCLOSE, 0666);
if (fd < 0)
sysfatal("create: %r");
fprint(fd, "%d\n", p[1]);
close(p[1]);
}
static int
inczoom(int n) {
int cz = zoom;
cz += n;
if (cz > maxzoom)
cz = maxzoom;
if (cz < 0)
cz = 0;
currentloc.z = cz;
cz = currentloc.z == zoom ? Cnil : Credraw;
zoom = currentloc.z;
currentloc = getbundle(gpsloc, currentloc.z, &drawoffset);
return cz;
}
static int
handlekeyboard(int kbdc)
{
double off = 100./(currentloc.z <= 0 ? 1 : currentloc.z*tilesize);
switch (kbdc) {
case Kdel:
case 'q':
exits(nil);
case '.':
return inczoom(+1);
case ',':
return inczoom(-1);
case Kleft:
gpsloc.lon -= off;
goto Loc;
case Kright:
gpsloc.lon += off;
goto Loc;
case Kup:
gpsloc.lat += off;
goto Loc;
case Kdown:
gpsloc.lat -= off;
goto Loc;
}
return Cnil;
Loc:
currentloc = getbundle(gpsloc, currentloc.z, &drawoffset);
return Credraw;
}
void
handlecmd(int cmd)
{
switch (cmd) {
case Credraw:
redrawmap();
return;
case Cnil:
default:
break;
}
}
static void
initmapfs(void)
{
int fd, n;
char buf[32];
fd = open("/mnt/map/ctl", OREAD);
if (fd < 0)
sysfatal("mapfs error: open ctl: %r");
n = read(fd, buf, sizeof(buf) - 1);
if (n < 0)
sysfatal("mapfs error: read ctl: %r");
close(fd);
buf[n] = 0;
maxzoom = atoi(buf);
}
void
main(int argc, char **argv)
{
Event ev;
int timer;
int cmd;
ARGBEGIN{
case 'd':
debug++;
}ARGEND;
runchecks();
if (debug)
traperrout();
initmapfs();
gpsloc = getlocation();
currentloc = getbundle(gpsloc, zoom, &drawoffset);
if (initdraw(nil, nil, "map") < 0)
sysfatal("%r");
nateborders = 0;
natetracedraw = debug;
if (debug)
natedebugfd = 2;
einit(Emouse|Ekeyboard);
timer = etimer(0, 100);
nateinit();
NAssign(NWindow, &mainwindow, New_Window(nil))
->MakeRoot()
->Slot(NSlot(),
New_VBox(nil)
->Slot(NSlotx(TOPLEFT, FILLX),
New_HBox("menu")
->Slot(NSlotx(LEFT, 0),
New_Button("bexit")
->Border(1, display->black)
->Label("Exit")
->OnClick(exitclicked, nil)
)
->Slot(NSlotx(LEFT, 0),
New_Button("btest")
->Border(1, display->black)
->Label("Test")
)
)
->Slot(NSlot(),
New_Box(nil)
->Border(1, display->black)
->Slot(NSlot(),
NAssign(NImage, &nimage, New_Image("map"))
)
)
->Slot(NSlotx(LEFT, FILLX),
New_Box("status")
->Border(1, display->black)
->Padding(NMargin2(5, 5))
->Slot(NSlot(),
New_Label(nil)
->Label("Status Line")
->Align(LEFT)
)
)
);
initimage();
redrawmap();
for (;;) {
cmd = event(&ev);
if (cmd == timer) {
checkcondredraw();
continue;
}
switch (cmd) {
case Emouse:
if (ev.mouse.buttons & 4)
exits(nil);
else
natemouseevent(ev.mouse);
break;
case Ekeyboard:
cmd = handlekeyboard(ev.kbdc);
handlecmd(cmd);
break;
}
}
}