]> git.cworth.org Git - grrobot/blob - src/grr_board_view.c
Ripped out leftover code from widget sample code.
[grrobot] / src / grr_board_view.c
1 /* grr_board_view - GTK+ widget for displaying an rr_board
2  *
3  * Copyright © 2003 Carl Worth
4  *
5  * Permission to use, copy, modify, distribute, and sell this software
6  * and its documentation for any purpose is hereby granted without
7  * fee, provided that the above copyright notice appear in all copies
8  * and that both that copyright notice and this permission notice
9  * appear in supporting documentation, and that the name of Carl Worth
10  * not be used in advertising or publicity pertaining to distribution
11  * of the software without specific, written prior permission.
12  * Carl Worth makes no representations about the suitability of this
13  * software for any purpose.  It is provided "as is" without express
14  * or implied warranty.
15  * 
16  * CARL WORTH DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
18  * NO EVENT SHALL CARL WORTH BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
20  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
21  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: Carl Worth <carl@theworths.org>
25  */
26
27 #include <Xr.h>
28 #include <xsvg.h>
29
30 #include <math.h>
31 #include <stdio.h>
32 #include <gtk/gtkmain.h>
33 #include <gtk/gtksignal.h>
34 #include <gdk/gdkx.h>
35
36 #include "grr_board_view.h"
37
38 #define SCROLL_DELAY_LENGTH  300
39 #define GRR_BOARD_VIEW_DEFAULT_SIZE 100
40
41 #define GRR_SVG_ASSUMED_WIDTH 32.0
42 #define GRR_SVG_ASSUMED_HEIGHT 32.0
43
44 #define GRR_CELL_SVG "svg/cell.svg"
45 #define GRR_WALL_SVG "svg/wall.svg"
46
47 #define GRR_ROBOT_BLUE_SVG "svg/robot_blue.svg"
48 #define GRR_ROBOT_GREEN_SVG "svg/robot_green.svg"
49 #define GRR_ROBOT_RED_SVG "svg/robot_red.svg"
50 #define GRR_ROBOT_YELLOW_SVG "svg/robot_yellow.svg"
51
52 #define GRR_TARGET_BLUE_CIRCLE_SVG "svg/target_blue_circle.svg"
53 #define GRR_TARGET_BLUE_OCTAGON_SVG "svg/target_blue_octagon.svg"
54 #define GRR_TARGET_BLUE_SQUARE_SVG "svg/target_blue_square.svg"
55 #define GRR_TARGET_BLUE_TRIANGLE_SVG "svg/target_blue_triangle.svg"
56
57 #define GRR_TARGET_GREEN_CIRCLE_SVG "svg/target_green_circle.svg"
58 #define GRR_TARGET_GREEN_OCTAGON_SVG "svg/target_green_octagon.svg"
59 #define GRR_TARGET_GREEN_SQUARE_SVG "svg/target_green_square.svg"
60 #define GRR_TARGET_GREEN_TRIANGLE_SVG "svg/target_green_triangle.svg"
61
62 #define GRR_TARGET_RED_CIRCLE_SVG "svg/target_red_circle.svg"
63 #define GRR_TARGET_RED_OCTAGON_SVG "svg/target_red_octagon.svg"
64 #define GRR_TARGET_RED_SQUARE_SVG "svg/target_red_square.svg"
65 #define GRR_TARGET_RED_TRIANGLE_SVG "svg/target_red_triangle.svg"
66
67 #define GRR_TARGET_YELLOW_CIRCLE_SVG "svg/target_yellow_circle.svg"
68 #define GRR_TARGET_YELLOW_OCTAGON_SVG "svg/target_yellow_octagon.svg"
69 #define GRR_TARGET_YELLOW_SQUARE_SVG "svg/target_yellow_square.svg"
70 #define GRR_TARGET_YELLOW_TRIANGLE_SVG "svg/target_yellow_triangle.svg"
71
72 #define GRR_TARGET_WHIRL_SVG "svg/target_whirl.svg"
73
74
75 /* Forward declarations */
76
77 static void grr_board_view_class_init               (grr_board_view_class_t    *klass);
78 static void grr_board_view_init                     (grr_board_view_t         *view);
79 static void grr_board_view_destroy                  (GtkObject        *object);
80 static void grr_board_view_realize                  (GtkWidget        *widget);
81 static void grr_board_view_size_request             (GtkWidget      *widget,
82                                                GtkRequisition *requisition);
83 static void grr_board_view_size_allocate            (GtkWidget     *widget,
84                                                GtkAllocation *allocation);
85 static gint grr_board_view_expose                   (GtkWidget        *widget,
86                                                 GdkEventExpose   *event);
87 static gint grr_board_view_button_press             (GtkWidget        *widget,
88                                                 GdkEventButton   *event);
89 static gint grr_board_view_button_release           (GtkWidget        *widget,
90                                                 GdkEventButton   *event);
91 static gint grr_board_view_motion_notify            (GtkWidget        *widget,
92                                                 GdkEventMotion   *event);
93
94 static void grr_board_view_update_mouse             (grr_board_view_t *view, gint x, gint y);
95 static void grr_board_view_update                   (grr_board_view_t *view);
96
97 /* Local data */
98
99 static GtkWidgetClass *parent_class = NULL;
100
101 GType
102 grr_board_view_get_type ()
103 {
104   static GType view_type = 0;
105
106   if (!view_type)
107     {
108       static const GTypeInfo view_info =
109       {
110         sizeof (grr_board_view_class_t),
111         NULL,
112         NULL,
113         (GClassInitFunc) grr_board_view_class_init,
114         NULL,
115         NULL,
116         sizeof (grr_board_view_t),
117         0,
118         (GInstanceInitFunc) grr_board_view_init,
119       };
120
121       view_type = g_type_register_static (GTK_TYPE_WIDGET, "grr_board_view", &view_info, 0);
122     }
123
124   return view_type;
125 }
126
127 static void
128 grr_board_view_class_init (grr_board_view_class_t *class)
129 {
130   GtkObjectClass *object_class;
131   GtkWidgetClass *widget_class;
132
133   object_class = (GtkObjectClass*) class;
134   widget_class = (GtkWidgetClass*) class;
135
136   parent_class = gtk_type_class (gtk_widget_get_type ());
137
138   object_class->destroy = grr_board_view_destroy;
139
140   widget_class->realize = grr_board_view_realize;
141   widget_class->expose_event = grr_board_view_expose;
142   widget_class->size_request = grr_board_view_size_request;
143   widget_class->size_allocate = grr_board_view_size_allocate;
144   widget_class->button_press_event = grr_board_view_button_press;
145   widget_class->button_release_event = grr_board_view_button_release;
146   widget_class->motion_notify_event = grr_board_view_motion_notify;
147 }
148
149 static void
150 grr_board_view_init (grr_board_view_t *view)
151 {
152     view->board = NULL;
153     view->owns_board = 0;
154     
155     view->button = 0;
156     view->timer = 0;
157 }
158
159 GtkWidget*
160 grr_board_view_new (rr_board_t *board)
161 {
162     grr_board_view_t *view;
163     
164     view = g_object_new (grr_board_view_get_type (), NULL);
165
166     if (board == NULL) {
167         board = rr_board_create (16, 16);
168         view->owns_board = 1;
169     }
170
171     grr_board_view_set_board (view, board);
172
173     return GTK_WIDGET (view);
174 }
175
176 static void
177 grr_board_view_destroy (GtkObject *object)
178 {
179     grr_board_view_t *view;
180
181     g_return_if_fail (object != NULL);
182     g_return_if_fail (GRR_IS_BOARD_VIEW (object));
183
184     view = GRR_BOARD_VIEW (object);
185
186     rr_board_destroy (view->board);
187
188     if (view->board && view->owns_board) {
189         rr_board_destroy (view->board);
190         view->board = NULL;
191     }
192     
193     if (GTK_OBJECT_CLASS (parent_class)->destroy)
194         (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
195 }
196
197 void
198 grr_board_view_set_board (grr_board_view_t      *view,
199                           rr_board_t *board)
200 {
201     g_return_if_fail (view != NULL);
202     g_return_if_fail (GRR_IS_BOARD_VIEW (view));
203
204     view->board = board;
205
206     grr_board_view_update (view);
207 }
208
209 static void
210 grr_board_view_realize (GtkWidget *widget)
211 {
212     grr_board_view_t *view;
213     GdkWindowAttr attributes;
214     gint attributes_mask;
215
216     g_return_if_fail (widget != NULL);
217     g_return_if_fail (GRR_IS_BOARD_VIEW (widget));
218   
219     GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
220     view = GRR_BOARD_VIEW (widget);
221
222     attributes.x = widget->allocation.x;
223     attributes.y = widget->allocation.y;
224     attributes.width = widget->allocation.width;
225     attributes.height = widget->allocation.height;
226     attributes.wclass = GDK_INPUT_OUTPUT;
227     attributes.window_type = GDK_WINDOW_CHILD;
228     attributes.event_mask = gtk_widget_get_events (widget) | 
229         GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | 
230         GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK |
231         GDK_POINTER_MOTION_HINT_MASK;
232     attributes.visual = gtk_widget_get_visual (widget);
233     attributes.colormap = gtk_widget_get_colormap (widget);
234     
235     attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
236     widget->window = gdk_window_new (widget->parent->window, &attributes, attributes_mask);
237     
238     widget->style = gtk_style_attach (widget->style, widget->window);
239     
240     gdk_window_set_user_data (widget->window, widget);
241
242     gtk_style_set_background (widget->style, widget->window, GTK_STATE_ACTIVE);
243 }
244
245 static void 
246 grr_board_view_size_request (GtkWidget      *widget,
247                        GtkRequisition *requisition)
248 {
249     requisition->width = GRR_BOARD_VIEW_DEFAULT_SIZE;
250     requisition->height = GRR_BOARD_VIEW_DEFAULT_SIZE;
251 }
252
253 static void
254 grr_board_view_size_allocate (GtkWidget     *widget,
255                         GtkAllocation *allocation)
256 {
257     grr_board_view_t *view;
258
259     g_return_if_fail (widget != NULL);
260     g_return_if_fail (GRR_IS_BOARD_VIEW (widget));
261     g_return_if_fail (allocation != NULL);
262
263     widget->allocation = *allocation;
264     view = GRR_BOARD_VIEW (widget);
265
266     if (GTK_WIDGET_REALIZED (widget)) {
267         gdk_window_move_resize (widget->window,
268                                 allocation->x, allocation->y,
269                                 allocation->width, allocation->height);
270     }
271 }
272
273 static void
274 grr_svg_draw (XrState *xrs, char *svg)
275 {
276     xsvg_status_t status;
277     xsvg_t *xsvg;
278
279     status = xsvg_create (&xsvg);
280     if (status) {
281         fprintf (stderr, "xsvg_create error\n");
282         return;
283     }
284     status = xsvg_parse_file (xsvg, svg);
285     if (status) {
286         fprintf (stderr, "xsvg_parse_file error parsing %s\n", svg);
287         return;
288     }
289     xsvg_render (xsvg, xrs);
290     if (status) {
291         fprintf (stderr, "xsvg_render error\n");
292         return;
293     }
294     xsvg_destroy (xsvg);
295 }
296
297 static void
298 grr_wall_draw (XrState *xrs, rr_wall_t wall)
299 {
300     char *wall_svg = GRR_WALL_SVG;
301
302     if (wall == RR_WALL_NONE)
303         return;
304
305     if (wall & RR_WALL_ABOVE) {
306         grr_svg_draw (xrs, wall_svg);
307     }
308     if (wall & RR_WALL_LEFT) {
309         XrSave (xrs);
310         XrRotate (xrs, M_PI_2);
311         grr_svg_draw (xrs, wall_svg);
312         XrRestore (xrs);
313     }
314     if (wall & RR_WALL_RIGHT) {
315         XrSave (xrs);
316         XrTranslate (xrs, GRR_SVG_ASSUMED_WIDTH, 0);
317         XrRotate (xrs, M_PI_2);
318         grr_svg_draw (xrs, wall_svg);
319         XrRestore (xrs);
320     }
321     if (wall & RR_WALL_BELOW) {
322         XrSave (xrs);
323         XrTranslate (xrs, 0, GRR_SVG_ASSUMED_HEIGHT);
324         grr_svg_draw (xrs, wall_svg);
325         XrRestore (xrs);
326     }
327 }
328
329 static void
330 grr_target_draw (XrState *xrs, rr_target_t target)
331 {
332     char *target_svg;
333
334     if (target == RR_TARGET_NONE)
335         return;
336
337     switch (target) {
338     case RR_TARGET_BLUE_CIRCLE:
339         target_svg = GRR_TARGET_BLUE_CIRCLE_SVG;
340         break;
341     case RR_TARGET_BLUE_OCTAGON:
342         target_svg = GRR_TARGET_BLUE_OCTAGON_SVG;
343         break;
344     case RR_TARGET_BLUE_SQUARE:
345         target_svg = GRR_TARGET_BLUE_SQUARE_SVG;
346         break;
347     case RR_TARGET_BLUE_TRIANGLE:
348         target_svg = GRR_TARGET_BLUE_TRIANGLE_SVG;
349         break;
350     case RR_TARGET_GREEN_CIRCLE:
351         target_svg = GRR_TARGET_GREEN_CIRCLE_SVG;
352         break;
353     case RR_TARGET_GREEN_OCTAGON:
354         target_svg = GRR_TARGET_GREEN_OCTAGON_SVG;
355         break;
356     case RR_TARGET_GREEN_SQUARE:
357         target_svg = GRR_TARGET_GREEN_SQUARE_SVG;
358         break;
359     case RR_TARGET_GREEN_TRIANGLE:
360         target_svg = GRR_TARGET_GREEN_TRIANGLE_SVG;
361         break;
362     case RR_TARGET_RED_CIRCLE:
363         target_svg = GRR_TARGET_RED_CIRCLE_SVG;
364         break;
365     case RR_TARGET_RED_OCTAGON:
366         target_svg = GRR_TARGET_RED_OCTAGON_SVG;
367         break;
368     case RR_TARGET_RED_SQUARE:
369         target_svg = GRR_TARGET_RED_SQUARE_SVG;
370         break;
371     case RR_TARGET_RED_TRIANGLE:
372         target_svg = GRR_TARGET_RED_TRIANGLE_SVG;
373         break;
374     case RR_TARGET_YELLOW_CIRCLE:
375         target_svg = GRR_TARGET_YELLOW_CIRCLE_SVG;
376         break;
377     case RR_TARGET_YELLOW_OCTAGON:
378         target_svg = GRR_TARGET_YELLOW_OCTAGON_SVG;
379         break;
380     case RR_TARGET_YELLOW_SQUARE:
381         target_svg = GRR_TARGET_YELLOW_SQUARE_SVG;
382         break;
383     case RR_TARGET_YELLOW_TRIANGLE:
384         target_svg = GRR_TARGET_YELLOW_TRIANGLE_SVG;
385         break;
386     case RR_TARGET_WHIRL:
387         target_svg = GRR_TARGET_WHIRL_SVG;
388         break;
389     default:
390         return;
391     }
392
393     grr_svg_draw (xrs, target_svg);
394 }
395
396 static void
397 grr_robot_draw (XrState *xrs, rr_robot_t robot)
398 {
399     char *robot_svg;
400
401     if (robot == RR_ROBOT_NONE)
402         return;
403
404     switch (robot) {
405     case RR_ROBOT_BLUE:
406         robot_svg = GRR_ROBOT_BLUE_SVG;
407         break;
408     case RR_ROBOT_GREEN:
409         robot_svg = GRR_ROBOT_GREEN_SVG;
410         break;
411     case RR_ROBOT_RED:
412         robot_svg = GRR_ROBOT_RED_SVG;
413         break;
414     case RR_ROBOT_YELLOW:
415         robot_svg = GRR_ROBOT_YELLOW_SVG;
416         break;
417     default:
418         return;
419     }
420
421     grr_svg_draw (xrs, robot_svg);
422 }
423
424 static void
425 grr_cell_draw (XrState *xrs, rr_cell_t cell, rr_target_t goal,
426                int width, int height)
427 {
428     int xpad, ypad;
429     rr_target_t target;
430
431     XrSave (xrs);
432     XrScale (xrs,
433              width / GRR_SVG_ASSUMED_WIDTH,
434              height / GRR_SVG_ASSUMED_HEIGHT);
435     grr_svg_draw (xrs, GRR_CELL_SVG);
436     grr_wall_draw (xrs, RR_CELL_GET_WALLS (cell));
437     XrRestore (xrs);
438
439     xpad = width / 5;
440     ypad = width / 5;
441
442     XrSave (xrs);
443     XrTranslate (xrs, xpad, ypad);
444     XrScale (xrs,
445              (width - 2*xpad)  / GRR_SVG_ASSUMED_WIDTH,
446              (height - 2*ypad) / GRR_SVG_ASSUMED_HEIGHT);
447
448     target = RR_CELL_GET_TARGET (cell);
449     grr_target_draw (xrs, target);
450     XrRestore (xrs);
451
452     /* This is a hack, (it obscures the cell background in addition to
453        the target). The real way to do this is to draw the target
454        itself with less opacity. */
455     if (target && target != goal) {
456         XrSave (xrs);
457         XrScale (xrs,
458                  width / GRR_SVG_ASSUMED_WIDTH,
459                  height / GRR_SVG_ASSUMED_HEIGHT);
460         XrRectangle (xrs, 0, 0,
461                      GRR_SVG_ASSUMED_WIDTH,
462                      GRR_SVG_ASSUMED_HEIGHT);
463         XrSetRGBColor (xrs, 1, 1, 1);
464         XrSetAlpha (xrs, 0.75);
465         XrFill (xrs);
466         XrRestore (xrs);
467     }
468
469     XrSave (xrs);
470     XrTranslate (xrs, xpad, ypad);
471     XrScale (xrs,
472              (width - 2*xpad)  / GRR_SVG_ASSUMED_WIDTH,
473              (height - 2*ypad) / GRR_SVG_ASSUMED_HEIGHT);
474
475     grr_robot_draw (xrs, RR_CELL_GET_ROBOT (cell));
476
477     XrRestore (xrs);
478
479 }
480
481 static gint
482 grr_board_view_expose (GtkWidget      *widget,
483                        GdkEventExpose *event)
484 {
485     grr_board_view_t *view;
486     Display *dpy;
487     Drawable drawable;
488     XrState *xrs;
489     GdkDrawable *real_drawable;
490     gint x_off, y_off;
491     int i, j;
492     rr_target_t goal_target;
493
494     g_return_val_if_fail (widget != NULL, FALSE);
495     g_return_val_if_fail (GRR_IS_BOARD_VIEW (widget), FALSE);
496     g_return_val_if_fail (event != NULL, FALSE);
497
498     if (event->count > 0)
499         return FALSE;
500
501     view = GRR_BOARD_VIEW (widget);
502
503     /* Unabstract X from GTK+ */
504     gdk_window_get_internal_paint_info (widget->window, &real_drawable, &x_off, &y_off);
505     dpy = gdk_x11_drawable_get_xdisplay (real_drawable);
506     drawable = gdk_x11_drawable_get_xid (real_drawable);
507
508     /* Ignore GTK+ and use Xr for drawing. */
509     xrs = XrCreate ();
510     XrSetTargetDrawable (xrs, dpy, drawable);
511     XrTranslate (xrs, -x_off, -y_off);
512
513     rr_board_get_size (view->board, &view->board_width, &view->board_height);
514
515     view->cell_width = widget->allocation.width / view->board_width;
516     if (view->cell_width == 0)
517         view->cell_width = 1;
518     view->cell_height = widget->allocation.height / view->board_height;
519     if (view->cell_height == 0)
520         view->cell_height = 1;
521
522     view->board_pad_x = (widget->allocation.width - view->board_width * view->cell_width) / 2;
523     view->board_pad_y = (widget->allocation.height - view->board_height * view->cell_height) / 2;
524
525     XrTranslate (xrs, view->board_pad_x, view->board_pad_y);
526
527     goal_target = rr_board_get_goal_target (view->board);
528
529     /* Draw cell targets */
530     for (j=0; j < view->board_height; j++) {
531         for (i=0; i < view->board_width; i++) {
532             XrSave (xrs);
533             XrTranslate (xrs, i * view->cell_width, j * view->cell_height);
534             grr_cell_draw (xrs,
535                            rr_board_get_cell (view->board, i, j),
536                            goal_target,
537                            view->cell_width, view->cell_height);
538             XrRestore (xrs);
539         }
540     }
541
542     /* Draw grid. */
543     XrSave (xrs);
544     XrSetRGBColor (xrs, .75, .75, 1);
545     XrSetLineWidth (xrs, 1);
546     for (j=0; j < view->board_height; j++) {
547         XrMoveTo (xrs, 0, j * view->cell_height + 0.5);
548         XrRelLineTo (xrs, view->board_width * view->cell_width, 0);
549     }
550     for (i=0; i < view->board_width; i++) {
551         XrMoveTo (xrs, i * view->cell_width + 0.5, 0);
552         XrRelLineTo (xrs, 0, view->board_height * view->cell_height);
553     }
554     XrStroke (xrs);
555     XrRestore (xrs);
556
557     /* Draw goal target in center of board */
558     XrSave (xrs);
559     XrTranslate (xrs,
560                  (view->board_width / 2 - 1) * view->cell_width,
561                  (view->board_height / 2 - 1) * view->cell_height);
562     grr_cell_draw (xrs, goal_target, goal_target,
563                    view->cell_width * 2, view->cell_height * 2);
564     XrRestore (xrs);
565
566     /* Draw walls */
567     for (j=0; j < view->board_height; j++) {
568         for (i=0; i < view->board_width; i++) {
569             XrSave (xrs);
570             XrTranslate (xrs, i * view->cell_width, j * view->cell_height);
571             XrScale (xrs,
572                      view->cell_width / GRR_SVG_ASSUMED_WIDTH,
573                      view->cell_height / GRR_SVG_ASSUMED_HEIGHT);
574             grr_wall_draw (xrs, RR_CELL_GET_WALLS (rr_board_get_cell(view->board, i, j)));
575             XrRestore (xrs);
576         }
577     }
578     
579     XrDestroy (xrs);
580
581     return FALSE;
582 }
583
584 /*
585 static void
586 grr_board_view_pointer_coords_to_grid (grr_board_view_t *view,
587                                        int pointer_x, int pointer_y,
588                                        int *grid_x, af
589 */
590 static gint
591 grr_board_view_button_press (GtkWidget      *widget,
592                        GdkEventButton *event)
593 {
594   grr_board_view_t *view;
595
596   g_return_val_if_fail (widget != NULL, FALSE);
597   g_return_val_if_fail (GRR_IS_BOARD_VIEW (widget), FALSE);
598   g_return_val_if_fail (event != NULL, FALSE);
599
600   view = GRR_BOARD_VIEW (widget);
601
602 /*
603   grr_board_view_pointer_coords_to_grid (view, event->x, event->y, &i, &j);
604 */
605   
606 /*
607   if (!view->button &&
608       rr_board_has_robot (view->board, i, j))
609     {
610       gtk_grab_add (widget);
611
612       view->button = event->button;
613
614       grr_board_view_update_mouse (view, event->x, event->y);
615     }
616   */
617
618   return FALSE;
619 }
620
621 static gint
622 grr_board_view_button_release (GtkWidget      *widget,
623                           GdkEventButton *event)
624 {
625   grr_board_view_t *view;
626
627   g_return_val_if_fail (widget != NULL, FALSE);
628   g_return_val_if_fail (GRR_IS_BOARD_VIEW (widget), FALSE);
629   g_return_val_if_fail (event != NULL, FALSE);
630
631   view = GRR_BOARD_VIEW (widget);
632
633   if (view->button == event->button) {
634 /*
635       gtk_grab_remove (widget);
636 */
637
638       view->button = 0;
639
640 /*
641       grr_board_view_pointer_coords_to_grid (view, event->x, event->y, &i, &j);
642 */
643
644       /* XXX: Need to compute direction based on (i, j) and old (i, j) */
645 /*
646       rr_client_move (view->client, view->robot, direction);
647 */
648
649   }
650
651   return FALSE;
652 }
653
654 static gint
655 grr_board_view_motion_notify (GtkWidget      *widget,
656                          GdkEventMotion *event)
657 {
658     grr_board_view_t *view;
659     GdkModifierType mods;
660     gint x, y, mask;
661     
662     g_return_val_if_fail (widget != NULL, FALSE);
663     g_return_val_if_fail (GRR_IS_BOARD_VIEW (widget), FALSE);
664     g_return_val_if_fail (event != NULL, FALSE);
665     
666     view = GRR_BOARD_VIEW (widget);
667     
668     if (view->button != 0) {
669         x = event->x;
670         y = event->y;
671
672         if (event->is_hint || (event->window != widget->window))
673             gdk_window_get_pointer (widget->window, &x, &y, &mods);
674         
675         switch (view->button) {
676         case 1:
677             mask = GDK_BUTTON1_MASK;
678             break;
679         case 2:
680             mask = GDK_BUTTON2_MASK;
681             break;
682         case 3:
683             mask = GDK_BUTTON3_MASK;
684             break;
685         default:
686             mask = 0;
687             break;
688         }
689
690         if (mods & mask)
691             grr_board_view_update_mouse (view, x,y);
692     }
693
694     return FALSE;
695 }
696
697 static void
698 grr_board_view_update_mouse (grr_board_view_t *view, gint x, gint y)
699 {
700     gint xc, yc;
701
702     g_return_if_fail (view != NULL);
703     g_return_if_fail (GRR_IS_BOARD_VIEW (view));
704
705     xc = GTK_WIDGET(view)->allocation.width / 2;
706     yc = GTK_WIDGET(view)->allocation.height / 2;
707 }
708
709 static void
710 grr_board_view_update (grr_board_view_t *view)
711 {
712     g_return_if_fail (view != NULL);
713     g_return_if_fail (GRR_IS_BOARD_VIEW (view));
714
715     gtk_widget_queue_draw (GTK_WIDGET (view));
716 }