2014-06-08 10:13:29 +04:00
|
|
|
/* This file is part of ToaruOS and is released under the terms
|
|
|
|
* of the NCSA / University of Illinois License - see LICENSE.md
|
|
|
|
* Copyright (C) 2013-2014 Kevin Lange
|
|
|
|
*/
|
2012-07-07 08:08:28 +04:00
|
|
|
/*
|
|
|
|
* clock-win
|
|
|
|
*
|
|
|
|
* Windowed Clock Application
|
|
|
|
*
|
|
|
|
* Creates a window that displays an analog clock.
|
|
|
|
*/
|
2012-03-29 05:34:28 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <time.h>
|
2013-04-17 10:05:29 +04:00
|
|
|
#include <cairo.h>
|
2014-04-16 07:08:21 +04:00
|
|
|
#include <unistd.h>
|
2014-05-12 04:40:16 +04:00
|
|
|
#include <sys/time.h>
|
2012-03-29 05:34:28 +04:00
|
|
|
|
|
|
|
#define PI 3.14159265
|
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
#include "lib/yutani.h"
|
2012-03-29 05:34:28 +04:00
|
|
|
#include "lib/graphics.h"
|
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
static yutani_t * yctx;
|
|
|
|
static yutani_window_t * window;
|
|
|
|
static gfx_context_t * w_ctx;
|
|
|
|
static int should_exit = 0;
|
2012-03-29 05:34:28 +04:00
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
static int32_t min(int32_t a, int32_t b) {
|
2012-03-29 05:34:28 +04:00
|
|
|
return (a < b) ? a : b;
|
|
|
|
}
|
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
static int32_t max(int32_t a, int32_t b) {
|
2012-03-29 05:34:28 +04:00
|
|
|
return (a > b) ? a : b;
|
|
|
|
}
|
2014-04-16 07:08:21 +04:00
|
|
|
|
|
|
|
static void draw(int secs) {
|
2012-03-29 05:34:28 +04:00
|
|
|
struct tm * timeinfo = localtime((time_t *)&secs);
|
2013-04-17 10:05:29 +04:00
|
|
|
draw_fill(w_ctx, rgba(0,0,0,0));
|
|
|
|
|
|
|
|
int stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, w_ctx->width);
|
|
|
|
cairo_surface_t * surface = cairo_image_surface_create_for_data(w_ctx->backbuffer, CAIRO_FORMAT_ARGB32, w_ctx->width, w_ctx->height, stride);
|
|
|
|
cairo_t * cr = cairo_create(surface);
|
|
|
|
|
|
|
|
cairo_set_line_width(cr, 9);
|
|
|
|
cairo_set_source_rgb(cr, 0.0,0.0,0.0);
|
|
|
|
cairo_translate(cr, w_ctx->width / 2, w_ctx->height / 2);
|
|
|
|
cairo_arc(cr, 0, 0, w_ctx->width / 2 - 10, 0, 2 * M_PI);
|
|
|
|
cairo_stroke_preserve(cr);
|
|
|
|
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
|
|
|
cairo_fill(cr);
|
|
|
|
|
|
|
|
uint16_t win_width = w_ctx->width;
|
2012-03-29 05:34:28 +04:00
|
|
|
|
2012-03-29 21:12:06 +04:00
|
|
|
{
|
2013-04-17 10:05:29 +04:00
|
|
|
int r1 = win_width * 3 / 7 - 9;
|
|
|
|
int r2 = win_width / 2 - 9;
|
2012-03-29 21:12:06 +04:00
|
|
|
for (int val = 0; val < 12; val += 1) {
|
|
|
|
double _val = (float)val / 12.0;
|
|
|
|
_val *= 2.0 * PI;
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
draw_line(w_ctx,
|
2013-04-17 10:05:29 +04:00
|
|
|
win_width / 2 + r1 * sin(_val), win_width / 2 + r2 * sin(_val),
|
|
|
|
win_width / 2 - r1 * cos(_val), win_width / 2 - r2 * cos(_val), rgb(0,0,0));
|
2012-03-29 21:12:06 +04:00
|
|
|
}
|
|
|
|
}
|
2012-03-29 05:34:28 +04:00
|
|
|
{ /* Hours */
|
|
|
|
double val = timeinfo->tm_hour;
|
2012-03-29 21:12:06 +04:00
|
|
|
val += (double)timeinfo->tm_min / 60.0;
|
2012-03-29 05:34:28 +04:00
|
|
|
if (val > 12.0)
|
|
|
|
val -= 12.0;
|
|
|
|
val /= 12.0;
|
|
|
|
val *= 2.0 * PI;
|
|
|
|
int radius = win_width * 1 / 4;
|
|
|
|
int left = win_width / 2 + radius * sin(val);
|
|
|
|
int top = win_width / 2 - radius * cos(val);
|
|
|
|
uint32_t color = rgb(0,0,0);
|
2013-04-17 10:05:29 +04:00
|
|
|
draw_line_thick(w_ctx, win_width / 2, left, win_width / 2, top, color, 2);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
|
|
|
{ /* Minutes */
|
|
|
|
double val = timeinfo->tm_min;
|
2012-03-29 21:12:06 +04:00
|
|
|
val += (double)timeinfo->tm_sec / 60.0;
|
2012-03-29 05:34:28 +04:00
|
|
|
val /= 60.0;
|
|
|
|
val *= 2.0 * PI;
|
2013-04-17 10:05:29 +04:00
|
|
|
int radius = win_width * 3 / 7 - 9;
|
2012-03-29 05:34:28 +04:00
|
|
|
int left = win_width / 2 + radius * sin(val);
|
|
|
|
int top = win_width / 2 - radius * cos(val);
|
|
|
|
uint32_t color = rgb(0,0,0);
|
2013-04-17 10:05:29 +04:00
|
|
|
draw_line_thick(w_ctx, win_width / 2, left, win_width / 2, top, color, 1);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
|
|
|
{ /* Seconds */
|
|
|
|
double val = timeinfo->tm_sec;
|
|
|
|
val /= 60.0;
|
|
|
|
val *= 2.0 * PI;
|
2013-04-17 10:05:29 +04:00
|
|
|
int radius = win_width * 3 / 7 - 9;
|
2012-03-29 05:34:28 +04:00
|
|
|
int left = win_width / 2 + radius * sin(val);
|
|
|
|
int top = win_width / 2 - radius * cos(val);
|
|
|
|
uint32_t color = rgb(255,0,0);
|
2013-04-17 10:05:29 +04:00
|
|
|
draw_line(w_ctx, win_width / 2, left, win_width / 2, top, color);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
|
|
|
|
2013-04-17 10:05:29 +04:00
|
|
|
cairo_surface_flush(surface);
|
|
|
|
cairo_destroy(cr);
|
|
|
|
cairo_surface_flush(surface);
|
|
|
|
cairo_surface_destroy(surface);
|
|
|
|
|
Context-based graphics library.
All graphics library commands now take a gfx_context_t pointer, which
points to a simple datastructure describing a rendering context (width,
height, depth, total size, front buffer, backbuffer; where backbuffer =
front buffer when not in double-buffering mode, thus we always render to
backbuffer except on a flip). This may have caused a minor speed
reduction, but I don't really care as it's far more important that we
support multiple graphics contexts.
TODO:
- Shared Memory Fonts library (there are a couple of apps that use these
so-called "shmem fonts" on their own; we need a dedicated library for
them)
- Break off "TTK" GUI toolkit into its own library. Since it's just a
callback-based button framework, this shouldn't be too hard right now.
Also, with the previous tick, I'll be able to put labels on controls
and start using text in more places.
2012-04-17 22:21:34 +04:00
|
|
|
flip(w_ctx);
|
2014-04-16 07:08:21 +04:00
|
|
|
yutani_flip(yctx, window);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
int main (int argc, char ** argv) {
|
|
|
|
int left = 100;
|
|
|
|
int top = 100;
|
|
|
|
int width = 200;
|
|
|
|
int height = 200;
|
|
|
|
|
|
|
|
yctx = yutani_init();
|
|
|
|
window = yutani_window_create(yctx, width, height);
|
|
|
|
yutani_window_move(yctx, window, left, top);
|
|
|
|
w_ctx = init_graphics_yutani_double_buffer(window);
|
2014-06-12 06:02:15 +04:00
|
|
|
yutani_window_update_shape(yctx, window, YUTANI_SHAPE_THRESHOLD_CLEAR);
|
2014-04-16 07:08:21 +04:00
|
|
|
|
|
|
|
while (!should_exit) {
|
2014-06-12 06:23:52 +04:00
|
|
|
yutani_msg_t * m = yutani_poll_async(yctx);
|
2014-04-16 07:08:21 +04:00
|
|
|
if (m) {
|
|
|
|
switch (m->type) {
|
|
|
|
case YUTANI_MSG_KEY_EVENT:
|
|
|
|
{
|
|
|
|
struct yutani_msg_key_event * ke = (void*)m->data;
|
|
|
|
if (ke->event.action == KEY_ACTION_DOWN && ke->event.keycode == 'q') {
|
|
|
|
should_exit = 1;
|
2014-06-12 22:10:56 +04:00
|
|
|
goto done;
|
2014-04-16 07:08:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2014-05-20 05:34:05 +04:00
|
|
|
case YUTANI_MSG_SESSION_END:
|
|
|
|
should_exit = 1;
|
2014-06-12 22:10:56 +04:00
|
|
|
goto done;
|
2014-04-16 07:08:21 +04:00
|
|
|
default:
|
|
|
|
break;
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
2014-04-16 07:22:02 +04:00
|
|
|
free(m);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
2014-06-12 06:23:52 +04:00
|
|
|
struct timeval now;
|
|
|
|
int last = 0;
|
|
|
|
|
2014-06-12 22:10:56 +04:00
|
|
|
gettimeofday(&now, NULL); //time(NULL);
|
|
|
|
if (now.tv_sec != last) {
|
|
|
|
last = now.tv_sec;
|
|
|
|
draw(last);
|
2014-06-12 06:23:52 +04:00
|
|
|
}
|
2014-06-12 22:10:56 +04:00
|
|
|
usleep(10000);
|
2012-03-29 05:34:28 +04:00
|
|
|
}
|
|
|
|
done:
|
|
|
|
|
2014-04-16 07:08:21 +04:00
|
|
|
yutani_close(yctx, window);
|
2012-03-29 05:34:28 +04:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2014-06-12 06:02:15 +04:00
|
|
|
|