ref: 6670406eb7bc3a815fe16a71b41a3cf265689fa7
dir: /clock.c/
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <event.h>
Point
circlept(Point c, int r, int degrees)
{
double rad = (double)degrees * PI / 180.0;
c.x += cos(rad) * r;
c.y -= sin(rad) * r;
return c;
}
void
lineb(Image* dst, Point p0, Point p1, Image* src)
{
int dx = abs(p1.x - p0.x), sx = p0.x < p1.x ? 1 : -1;
int dy = -abs(p1.y - p0.y), sy = p0.y < p1.y ? 1 : -1;
int err = dx + dy, e2;
for(;;) {
draw(dst, Rect(p0.x, p0.y, p0.x + 1, p0.y + 1), src, nil, ZP);
if(p0.x == p1.x && p0.y == p1.y)
break;
e2 = 2 * err;
if(e2 >= dy) {
err += dy;
p0.x += sx;
}
if(e2 <= dx) {
err += dx;
p0.y += sy;
}
}
}
void
redraw(Image* dst)
{
Point size = subpt(screen->r.max, screen->r.min);
Point center = divpt(size, 2);
Rectangle frame = (Rectangle){Pt(0, 0), size};
int pad = 10;
int rad = ((size.x < size.y ? size.x : size.y) / 2) - 2;
int range = rad - pad;
Image* view = allocimage(display, frame, screen->chan, 1, 0x000000FF);
Image* secclr = allocimagemix(display, DRed, DRed);
for(int i = 0; i < 60; i++) {
int len = i % 15 == 0 ? range : i % 5 == 0 ? rad - pad / 2 : rad - pad / 3;
lineb(view, circlept(center, len, i * 6), circlept(center, rad, i * 6), display->white);
}
Tm tms = *localtime(time(0));
int anghr = 90 - (tms.hour * 5 + tms.min / 12) * 6;
int angmin = 90 - tms.min * 6;
int angsec = 90 - tms.sec * 6;
int angsecrev = 270 - tms.sec * 6;
fillellipse(view, center, rad - pad, rad - pad, display->black, ZP);
lineb(view, center, circlept(center, range * 0.7, anghr), display->white);
lineb(view, center, circlept(center, range - 2, angmin), display->white);
lineb(view, center, circlept(center, range - 2, angsec), secclr);
lineb(view, center, circlept(center, range * 0.1, angsecrev), secclr);
fillellipse(view, center, 2, 2, secclr, ZP);
/* collapse when horizontal window */
if(size.y > size.x + 2 * pad) {
/* time */
char timestr[9];
snprint(timestr, sizeof(timestr), "%02d:%02d:%02d", tms.hour, tms.min, tms.sec);
Point timesize = stringsize(display->defaultfont, timestr);
Point timept = Pt(pad, pad);
/* date */
char datestr[30];
snprint(datestr, sizeof(datestr), "%s", ctime(time(0)));
datestr[10] = '\0';
Point datesize = stringsize(display->defaultfont, datestr);
Point datept = Pt(size.x - datesize.x - pad, pad);
/* draw */
draw(view,
(Rectangle){timept, addpt(timept, Pt(size.x - pad * 2, 0))},
display->black, nil, ZP);
string(view, timept, display->white, ZP, display->defaultfont, timestr);
if(timesize.x + datesize.x < size.x - pad - pad)
string(view, datept, display->white, ZP, display->defaultfont, datestr);
}
draw(dst, screen->r, view, nil, ZP);
flushimage(display, 1);
freeimage(secclr);
freeimage(view);
}
void
eresized(int new)
{
if(new&& getwindow(display, Refnone) < 0)
fprint(2, "can't reattach to window");
redraw(screen);
}
void
main(int argc, char* argv[])
{
USED(argc, argv);
Event e;
Mouse m;
Menu menu;
char* mstr[] = {"exit", 0};
int key, timer, t = 1000;
if(initdraw(0, 0, "clock") < 0)
sysfatal("initdraw failed");
eresized(0);
einit(Emouse);
timer = etimer(0, t);
menu.item = mstr;
menu.lasthit = 0;
for(;;) {
key = event(&e);
if(key == Emouse) {
m = e.mouse;
if(m.buttons & 4) {
if(emenuhit(3, &m, &menu) == 0)
exits(0);
}
} else if(key == timer) {
redraw(screen);
}
}
}