/* grr_board_view - GTK+ widget for displaying an rr_board
*
- * Copyright © 2003 Carl Worth
+ * Copyright © 2003 Carl Worth
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
#include <string.h>
#include <cairo.h>
-#include <xsvg.h>
+#include <cairo-xlib.h>
+#include <librsvg/rsvg.h>
+#include <librsvg/rsvg-cairo.h>
#include <gtk/gtkmain.h>
#include <gtk/gtksignal.h>
view->client = NULL;
view->button = 0;
+
+ view->time = 60.0;
+ view->drift_correct = 0.0;
view->timer = 0;
+ view->zap_time = 0.0;
view->cell_width = 0;
view->cell_height = 0;
rr_board_t *board;
Display *dpy;
Drawable drawable;
+ Visual *visual;
+ cairo_surface_t *surface;
cairo_t *xrs;
GdkDrawable *real_drawable;
gint x_off, y_off;
view = GRR_BOARD_VIEW (widget);
board = view->board;
- /* Unabstract X from GTK+ */
- gdk_window_get_internal_paint_info (widget->window, &real_drawable, &x_off, &y_off);
- dpy = gdk_x11_drawable_get_xdisplay (real_drawable);
- drawable = gdk_x11_drawable_get_xid (real_drawable);
-
- /* Ignore GTK+ and use Cairo for drawing. */
- xrs = cairo_create ();
- cairo_set_target_drawable (xrs, dpy, drawable);
+ xrs = gdk_cairo_create (widget->window);
new_cell_width = widget->allocation.width / view->board_width;
if (new_cell_width == 0)
cairo_translate (xrs, i * view->cell_width, j * view->cell_height);
if ((i+j) % 2 == 0)
- grr_icon_draw_predrawn (view->cell1_icon, xrs);
+ grr_icon_draw_predrawn (view->cell1_icon, xrs, 1.0);
else
- grr_icon_draw_predrawn (view->cell2_icon, xrs);
-
- if (target) {
- if (target && target != goal_target) {
- cairo_save (xrs);
- cairo_set_alpha (xrs, .25);
- cairo_set_operator (xrs, CAIRO_OPERATOR_XOR);
- grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)], xrs);
- cairo_set_alpha (xrs, 0.25);
- cairo_set_operator (xrs, CAIRO_OPERATOR_OVER);
- grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)], xrs);
- cairo_restore (xrs);
- } else {
- grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)], xrs);
- }
- }
+ grr_icon_draw_predrawn (view->cell2_icon, xrs, 1.0);
+
+ if (target)
+ grr_icon_draw_predrawn (view->target_icon[rr_target_idx (target)],
+ xrs,
+ target == goal_target ? 1.0 : 0.25);
if (robot)
- grr_icon_draw_predrawn (view->robot_icon[rr_robot_idx (robot)], xrs);
+ grr_icon_draw_predrawn (view->robot_icon[rr_robot_idx (robot)],
+ xrs, 1.0);
cairo_restore (xrs);
}
2 * view->cell_width / GRR_SVG_ASSUMED_WIDTH,
2 * view->cell_height / GRR_SVG_ASSUMED_HEIGHT);
cairo_rectangle (xrs, 0, 0, GRR_SVG_ASSUMED_WIDTH, GRR_SVG_ASSUMED_HEIGHT);
- cairo_set_rgb_color (xrs, 1, 1, 1);
+ cairo_set_source_rgb (xrs, 1, 1, 1);
cairo_fill (xrs);
grr_icon_draw (view->target_icon[rr_target_idx (goal_target)], xrs);
cairo_restore (xrs);
+
+ /* Draw clock */
+ if (view->time < 60.0) {
+ cairo_save (xrs);
+ cairo_new_path (xrs);
+ cairo_move_to (xrs,
+ (double) view->board_width / 2 * view->cell_width,
+ (double) view->board_height / 2 * view->cell_height);
+ cairo_arc (xrs,
+ (double) view->board_width / 2 * view->cell_width,
+ (double) view->board_height / 2 * view->cell_height,
+ .9 * view->cell_width,
+ - M_PI_2,
+ 2 * M_PI * (60.0 - view->time) / 60.0 - M_PI_2);
+ cairo_close_path (xrs);
+
+ cairo_set_source_rgba (xrs, 0.0, 0.0, 0.0, 0.5);
+ cairo_fill (xrs);
+
+ cairo_restore (xrs);
+ }
}
/* Draw walls */
grr_board_view_transform_cell_to_pixel (view, i, j, &x, &y);
gtk_widget_queue_draw_area (GTK_WIDGET (view), x, y, view->cell_width, view->cell_height);
}
+
+#define TIMER_INTERVAL_MS 100.0
+
+static void
+grr_board_view_refresh_timer (grr_board_view_t *view)
+{
+ int x, y;
+
+ grr_board_view_transform_cell_to_pixel (view,
+ view->board_width / 2 - 1,
+ view->board_height / 2 -1,
+ &x, &y);
+ gtk_widget_queue_draw_area (GTK_WIDGET (view),
+ x, y,
+ 2 * view->cell_width,
+ 2 * view->cell_height);
+}
+
+static gboolean
+grr_board_view_decrement_timer (void *widget)
+{
+ grr_board_view_t *view = widget;
+
+ view->time -= TIMER_INTERVAL_MS / 1000.0;
+ view->time += view->drift_correct;
+
+ if (view->zap_time) {
+ view->time -= view->zap_time;
+ view->zap_time += 1.0;
+ }
+
+ grr_board_view_refresh_timer (view);
+
+ if (view->time < 0) {
+ grr_board_view_stop_timer (view);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+grr_board_view_set_timer (grr_board_view_t *view, double time)
+{
+ /* XXX: It would be good to adjust the clock for latency somewhere... */
+ if (view->timer) {
+ double correction_time;
+ /* Correct any drift within the next 10 seconds, or half the
+ remaining time --- whichever is less. */
+ if (time >= 20.0)
+ correction_time = 10.0;
+ else
+ correction_time = time / 2.0;
+ view->drift_correct = (time - view->time) / (correction_time * TIMER_INTERVAL_MS);
+ } else {
+ view->time = time;
+ view->drift_correct = 0.0;
+ view->zap_time = 0.0;
+ }
+}
+
+void
+grr_board_view_start_timer (grr_board_view_t *view)
+{
+ if (view->timer)
+ return;
+
+ view->timer = gtk_timeout_add (TIMER_INTERVAL_MS, grr_board_view_decrement_timer, view);
+}
+
+void
+grr_board_view_stop_timer (grr_board_view_t *view)
+{
+ if (view->timer == 0)
+ return;
+
+ gtk_timeout_remove (view->timer);
+ view->timer = 0;
+ view->time = 0.0;
+ view->drift_correct = 0.0;
+ view->zap_time = 0.0;
+
+ grr_board_view_refresh_timer (view);
+}
+
+void
+grr_board_view_zap_timer (grr_board_view_t *view)
+{
+ view->zap_time = 4;
+
+ grr_board_view_refresh_timer (view);
+}
+