1 /**
2 \brief      This module implements the gnocl::drawingArea widget.
3 **/
4 
5 /**
6 \page page_drawingArea gnocl::drawingArea
7 \htmlinclude drawingArea.html
8 **/
9 
10 /**
11 \par Modification History
12 \verbatim
13 	2013-07: added commands, options, commands
14 \endverbatim
15 **/
16 
17 /* user documentation */
18 
19 #include "gnocl.h"
20 #include <gdk/gdkkeysyms.h>
21 
22 /*
23     The Widget implementation has a number of empty entries within its
24     options array. This will allow the coder to configure the widget
25     under scripted control, thereby providing a Gnocl framework for
26     customised widget creation.
27 */
28 
29 static gint _n = 7; /* counter,number of implemented widget options */
30 
31 static GnoclOption drawingAreaOptions[] =
32 {
33 	/* common widget options */
34 	{ "-tooltip", GNOCL_OBJ, "", gnoclOptTooltip },
35 	{ "-data", GNOCL_OBJ, "", gnoclOptData },
36 	{ "-name", GNOCL_STRING, "name" },
37 	{ "-onShowHelp", GNOCL_OBJ, "", gnoclOptOnShowHelp },
38 	{ "-cursor", GNOCL_OBJ, "", gnoclOptCursor },
39 	{ "-sensitive", GNOCL_BOOL, "sensitive" },
40 	{ "-visible", GNOCL_BOOL, "visible" },
41 
42 	/* widget specific options, 30 blank spaces */
43 	{ "", GNOCL_OBJ, "", NULL },
44 	{ "", GNOCL_OBJ, "", NULL },
45 	{ "", GNOCL_OBJ, "", NULL },
46 	{ "", GNOCL_OBJ, "", NULL },
47 	{ "", GNOCL_OBJ, "", NULL },
48 	{ "", GNOCL_OBJ, "", NULL },
49 	{ "", GNOCL_OBJ, "", NULL },
50 	{ "", GNOCL_OBJ, "", NULL },
51 	{ "", GNOCL_OBJ, "", NULL },
52 	{ "", GNOCL_OBJ, "", NULL },
53 	{ "", GNOCL_OBJ, "", NULL },
54 	{ "", GNOCL_OBJ, "", NULL },
55 	{ "", GNOCL_OBJ, "", NULL },
56 	{ "", GNOCL_OBJ, "", NULL },
57 	{ "", GNOCL_OBJ, "", NULL },
58 	{ "", GNOCL_OBJ, "", NULL },
59 	{ "", GNOCL_OBJ, "", NULL },
60 	{ "", GNOCL_OBJ, "", NULL },
61 	{ "", GNOCL_OBJ, "", NULL },
62 	{ "", GNOCL_OBJ, "", NULL },
63 	{ "", GNOCL_OBJ, "", NULL },
64 	{ "", GNOCL_OBJ, "", NULL },
65 	{ "", GNOCL_OBJ, "", NULL },
66 	{ "", GNOCL_OBJ, "", NULL },
67 	{ "", GNOCL_OBJ, "", NULL },
68 	{ "", GNOCL_OBJ, "", NULL },
69 	{ "", GNOCL_OBJ, "", NULL },
70 	{ "", GNOCL_OBJ, "", NULL },
71 	{ "", GNOCL_OBJ, "", NULL },
72 	{ "", GNOCL_OBJ, "", NULL },
73 	{ "", GNOCL_OBJ, "", NULL },
74 	{ "", GNOCL_OBJ, "", NULL },
75 	{ NULL },
76 };
77 
78 /*
79       GDK_EXPOSURE_MASK         GDK_POINTER_MOTION_MASK     GDK_POINTER_MOTION_HINT_MASK
80       GDK_BUTTON_MOTION_MASK    GDK_BUTTON1_MOTION_MASK     GDK_BUTTON2_MOTION_MASK
81       GDK_BUTTON3_MOTION_MASK   GDK_BUTTON_PRESS_MASK       GDK_BUTTON_RELEASE_MASK
82       GDK_KEY_PRESS_MASK        GDK_KEY_RELEASE_MASK        GDK_ENTER_NOTIFY_MASK
83       GDK_LEAVE_NOTIFY_MASK     GDK_FOCUS_CHANGE_MASK       GDK_STRUCTURE_MASK
84       GDK_PROPERTY_CHANGE_MASK  GDK_VISIBILITY_NOTIFY_MASK  GDK_PROXIMITY_IN_MASK
85       GDK_PROXIMITY_OUT_MASK    GDK_SUBSTRUCTURE_MASK       GDK_SCROLL_MASK
86       GDK_ALL_EVENTS_MASK
87 */
88 
89 static const char *options[] =
90 {
91 	"-onExpose",        "-onPointerMotion",  "motionHint",
92 	"-onButtonMotion",  "-onButton1Motion", "-onButton2Motion",
93 	"-onButton3Motion", "-onButtonPress",   "-onButtonRelease",
94 	"-onKeyPress",      "-onKeyRelease",    "-onEnter",
95 	"-onLeave",         "-onFocus",         "structure",
96 	"propertyChange",   "visibility",       "proximityIn",
97 	"proximityOut",     "substructure",     "-onScroll",
98 	"all",
99 	NULL
100 };
101 
102 enum OptsIdx
103 {
104 	OnExposeIdx,        OnPointerMotionIdx, PointerMotionHintIdx,
105 	OnButtonMotionIdx,  OnButton1MotionIdx, OnButton2MotionIdx,
106 	OnButton3MotionIdx, OnButtonPressIdx,   OnButtonReleaseIdx,
107 	OnKeyPressIdx,      OnKeyReleaseIdx,    OnEnterIdx,
108 	OnLeaveIdx,         OnFocusIdx,         StructureIdx,
109 	PropertyChangeIdx,  VisibilityIdx,      ProximityInIdx,
110 	ProximityOutIdx,    SubstructureIdx,    OnScrollIdx,
111 	AllIdx
112 };
113 
114 /**
115 \brief
116 **/
configure(Tcl_Interp * interp,GtkDrawingArea * area,GnoclOption options[])117 static int configure ( Tcl_Interp *interp, GtkDrawingArea *area, GnoclOption options[] )
118 {
119 
120 	gint ret = gnoclSetOptions ( interp, options, area, -1 );
121 
122 	return TCL_OK;
123 }
124 
125 static const char *cmds[] =
126 {
127 	"draw", "cget", "configure",
128 	"delete", "class", "erase",
129 	"option",
130 	NULL
131 };
132 
133 /**
134 /brief
135 **/
drawingAreaFunc(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])136 int drawingAreaFunc ( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj * const objv[] )
137 {
138 #ifdef DEBUG_DRAWING_AREA
139 	listParameters ( objc, objv, "drawingAreaFunc" );
140 #endif
141 
142 
143 	enum cmdIdx
144 	{
145 		DrawIdx, CgetIdx, ConfigureIdx,
146 		DeleteIdx, ClassIdx, EraseIdx,
147 		OptionIdx
148 	};
149 
150 	/*
151 	static const char *events[] =
152 	{
153 	    "expose",           "motion",           "motionHint",
154 	    "buttonMotion",     "button1Motion",    "button2Motion",
155 	    "button3Motion",    "buttonPress",      "buttonRelease",
156 	    "keyPress",         "keyRelease",       "enter",
157 	    "leave",            "focus",            "structure",
158 	    "propertyChange",   "visibility",       "proximityIn",
159 	    "proximityOut",     "substructure",     "scroll",
160 	    "all", NULL
161 	};
162 	*/
163 
164 	GtkWidget *area = GTK_WIDGET ( data );
165 
166 	int idx;
167 	int idx2;
168 
169 	if ( objc < 2 )
170 	{
171 		Tcl_WrongNumArgs ( interp, 1, objv, "command" );
172 		return TCL_ERROR;
173 	}
174 
175 	if ( Tcl_GetIndexFromObj ( interp, objv[1], cmds, "command", TCL_EXACT, &idx ) != TCL_OK )
176 	{
177 		return TCL_ERROR;
178 	}
179 
180 	switch ( idx )
181 	{
182 
183 		case OptionIdx:
184 			{
185 #ifdef DEBUG_DRAWING_AREA
186 				g_print ( "drawingArea OptionIdx\n" );
187 #endif
188 
189 				/*
190 				other options here could include:
191 				    remove      -remove the option from the options array (incl. script)
192 				    available   -return a list of currently configured options
193 				    suspend     -remove option from the event mask only
194 				    resume      -add the option to the event mask
195 				*/
196 
197 				if ( strcmp ( Tcl_GetString ( objv[2] ), "add" )  )
198 				{
199 					return TCL_ERROR;
200 				}
201 
202 
203 				/* determine how many items in the add list */
204 				gint noOptions;
205 				gint n;
206 
207 				Tcl_ListObjLength ( interp, objv[3], &noOptions );
208 
209 				for ( n = 0; n < noOptions; ++n )
210 				{
211 					GtkWidget *childWidget;
212 					Tcl_Obj *tp;
213 
214 					if ( Tcl_ListObjIndex ( interp,  objv[3], n, &tp ) != TCL_OK )
215 					{
216 						return TCL_ERROR;
217 					}
218 
219 					int OptIdx;
220 
221 					if ( Tcl_GetIndexFromObj ( interp, tp, options, "option", TCL_EXACT, &OptIdx ) != TCL_OK )
222 					{
223 						return TCL_ERROR;
224 					}
225 
226 					_n = doOptionAdd ( interp, area, OptIdx );
227 
228 				}
229 
230 				break;
231 			case ConfigureIdx:
232 				{
233 #ifdef DEBUG_DRAWING_AREA
234 					g_print ( "drawingArea ConfigureIdx\n" );
235 #endif
236 					int ret = TCL_ERROR;
237 
238 					if ( gnoclParseAndSetOptions ( interp, objc - 1, objv + 1, drawingAreaOptions, area ) == TCL_OK )
239 					{
240 						ret = configure ( interp, area, drawingAreaOptions );
241 					}
242 
243 					gnoclClearOptions ( drawingAreaOptions );
244 
245 					return ret;
246 				}
247 
248 				break;
249 			case DeleteIdx:
250 				{
251 #ifdef DEBUG_DRAWING_AREA
252 					g_print ( "delete\n" );
253 #endif
254 					return gnoclDelete ( interp, area, objc, objv );
255 				}
256 
257 				break;
258 			case ClassIdx:
259 				{
260 #ifdef DEBUG_DRAWING_AREA
261 					g_print ( "Class = drawingArea\n" );
262 #endif
263 					Tcl_SetObjResult ( interp, Tcl_NewStringObj ( "drawingArea", -1 ) );
264 				}
265 
266 				break;
267 			case DrawIdx:
268 				{
269 #ifdef DEBUG_DRAWING_AREA
270 					g_print ( "draw\n" );
271 #endif
272 					/* relocate these to relevant parts of the souce file */
273 					static const char *drawOpts[] =
274 					{
275 						"point", "points", "line",
276 						"lines", "pixbuf", "segments",
277 						"rectangle", "arc", "polygon",
278 						"trapezoids", "glyph", "glyphTransformed",
279 						"layoutLine", "layoutWithColors", "string",
280 						"text", "image", "queue",
281 						NULL
282 					};
283 
284 					enum drawOptsIdx
285 					{
286 						PointIdx, PointsIdx, LineIdx,
287 						LinesIdx, PixbufIdx, SegmentsIdx,
288 						RectangleIdx, ArcIdx, PolygonIdx,
289 						TrapezoidsIdx, GlyphIdx, GlyphTransformedIdx,
290 						LayoutLineIdx, LayoutWithColorsIdx, StringIdx,
291 						TextIdx, ImageIdx, QueueIdx
292 					};
293 
294 					gint idx2;
295 
296 					if ( Tcl_GetIndexFromObj ( interp, objv[2], drawOpts, "option", TCL_EXACT, &idx2 ) != TCL_OK )
297 					{
298 						return TCL_ERROR;
299 					}
300 
301 					switch ( idx2 )
302 					{
303 						case QueueIdx:
304 							{
305 								gtk_widget_queue_draw ( area );
306 							}
307 							break;
308 						case PointIdx:
309 							{
310 								g_print ( "drawing point %s\n", Tcl_GetString ( objv[3] ) );
311 								gint x, y;
312 								sscanf ( Tcl_GetString ( objv[3] ), "%d %d", &x, &y );
313 								gdk_draw_point ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], x, y );
314 							}
315 							break;
316 						case PointsIdx:
317 							{
318 
319 								int k, n, npoints, x, y;
320 								Tcl_ListObjLength ( interp, objv[3], &npoints );
321 								g_print ( "drawing points %s (%d)\n", Tcl_GetString ( objv[3] ), npoints  );
322 
323 
324 								GdkPoint points[npoints]; // = { {x, y} , {x + 1, y} , {x - 1, y} , {x, y + 1} , {x, y - 1} };
325 								k = 0;
326 
327 								for ( n = 0; n < npoints; n += 2 )
328 								{
329 									GtkWidget *childWidget;
330 									Tcl_Obj *tpx, *tpy;
331 
332 									if ( Tcl_ListObjIndex ( interp,  objv[3], n, &tpx ) != TCL_OK )
333 									{
334 										return TCL_ERROR;
335 									}
336 
337 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 1, &tpy ) != TCL_OK )
338 									{
339 										return TCL_ERROR;
340 									}
341 
342 									Tcl_GetIntFromObj ( interp, tpx, &x );
343 									Tcl_GetIntFromObj ( interp, tpy, &y );
344 
345 									g_print ( "points = %d: item %d x = %d : y = %d\n", npoints, k, x, y );
346 
347 									points[k].x = x;
348 									points[k].y = y;
349 									k++;
350 
351 								}
352 
353 								gdk_draw_points ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], points, npoints / 2 );
354 
355 							}
356 							break;
357 						case LineIdx:
358 							{
359 								g_print ( "drawing line %s\n", Tcl_GetString ( objv[3] ) );
360 								gint x1, y1, x2, y2;
361 								sscanf ( Tcl_GetString ( objv[3] ), "%d %d %d %d", &x1, &y1, &x2, &y2 );
362 								gdk_draw_line ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], x1, y1, x2, y2 );
363 							}
364 							break;
365 						case LinesIdx:
366 							{
367 
368 								int k, n, npoints, x, y;
369 								Tcl_ListObjLength ( interp, objv[3], &npoints );
370 								g_print ( "drawing lines %s (%d)\n", Tcl_GetString ( objv[3] ), npoints  );
371 
372 
373 								GdkPoint points[npoints]; // = { {x, y} , {x + 1, y} , {x - 1, y} , {x, y + 1} , {x, y - 1} };
374 								k = 0;
375 
376 								for ( n = 0; n < npoints; n += 2 )
377 								{
378 									GtkWidget *childWidget;
379 									Tcl_Obj *tpx, *tpy;
380 
381 									if ( Tcl_ListObjIndex ( interp,  objv[3], n, &tpx ) != TCL_OK )
382 									{
383 										return TCL_ERROR;
384 									}
385 
386 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 1, &tpy ) != TCL_OK )
387 									{
388 										return TCL_ERROR;
389 									}
390 
391 									Tcl_GetIntFromObj ( interp, tpx, &x );
392 									Tcl_GetIntFromObj ( interp, tpy, &y );
393 
394 									g_print ( "points = %d: item %d x = %d : y = %d\n", npoints, k, x, y );
395 
396 									points[k].x = x;
397 									points[k].y = y;
398 									k++;
399 
400 								}
401 
402 								gdk_draw_lines ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], points, npoints / 2 );
403 
404 
405 								//gdk_draw_lines (GdkDrawable *drawable, GdkGC *gc, const GdkPoint *points, gint n_points);
406 
407 							}
408 							break;
409 						case PixbufIdx:
410 							{
411 								g_print ( "drawing pixbuf %s\n", Tcl_GetString ( objv[3] ) );
412 								GdkPixbuf *pixbuf;
413 								GdkRgbDither dither;
414 								gint src_x, src_y, dest_x, dest_y, width, height;
415 								gint x_dither, y_dither;
416 								gint ret;
417 
418 								/* set some defaults */
419 								dither = GDK_RGB_DITHER_NONE;
420 								src_x = 0; src_y = 0;
421 								dest_x = 0; dest_y = 0;
422 								width = -1; height = -1;
423 								x_dither = 0; y_dither = 0;
424 
425 								pixbuf = gnoclGetPixBufFromName ( Tcl_GetString ( objv[3] ), interp );
426 
427 								width = gdk_pixbuf_get_width ( pixbuf );
428 								height = gdk_pixbuf_get_height ( pixbuf );
429 
430 								int Idx2;
431 								static const char *pbOpts[] =
432 								{
433 									"-from", "-to",
434 									"-dither", "-offset",
435 									NULL
436 								};
437 
438 								enum pbIdx
439 								{
440 									FromIdx, ToIdx,
441 									DitherIdx, OffsetIdx,
442 								};
443 
444 								/* parse all the options */
445 								int i = 4;
446 
447 								while ( i < objc )
448 								{
449 									//g_print ( "i = %d %s\n", i, Tcl_GetString ( objv[i] ) );
450 
451 									getIdx ( pbOpts, Tcl_GetString ( objv[i] ), &Idx2 );
452 
453 									switch ( Idx2 )
454 									{
455 										case FromIdx:
456 											{
457 
458 												ret = sscanf ( Tcl_GetString ( objv[i+1] ), "%d %d %d %d", &src_x, &src_y, &width, &height );
459 
460 												if ( ret < 2 )
461 												{
462 													return TCL_ERROR;
463 												}
464 
465 												g_print ( "-from %d %d %d %d\n", src_x, src_y, width, height );
466 											}
467 											break;
468 										case ToIdx:
469 											{
470 
471 												ret = sscanf ( Tcl_GetString ( objv[i+1] ), "%d %d", &dest_x, &dest_y );
472 
473 												if ( ret != 2 )
474 												{
475 													return TCL_ERROR;
476 												}
477 
478 												g_print ( "-to %d %d\n", dest_x, dest_y );
479 
480 											}
481 											break;
482 										case DitherIdx:
483 											{
484 												/* one of none, normal or max : defaul = none */
485 												if ( strcmp ( Tcl_GetString ( objv[i+1] ), "none" ) == 0 )
486 												{
487 													dither = GDK_RGB_DITHER_NONE;
488 												}
489 
490 												if ( strcmp ( Tcl_GetString ( objv[i+1] ), "normal" ) == 0 )
491 
492 												{
493 													dither = GDK_RGB_DITHER_NORMAL;
494 												}
495 
496 												if ( strcmp ( Tcl_GetString ( objv[i+1] ), "max" ) == 0 )
497 												{
498 													dither = GDK_RGB_DITHER_MAX;
499 												}
500 
501 												g_print ( "-dither %d\n", dither );
502 											}
503 
504 											break;
505 										case OffsetIdx:
506 											{
507 												ret = sscanf ( Tcl_GetString ( objv[i+1] ), "%d %d", &x_dither, &y_dither );
508 
509 												if ( ret != 2 )
510 												{
511 													return TCL_ERROR;
512 												}
513 
514 												g_print ( "-offset %d %d\n", x_dither, y_dither );
515 											}
516 											break;
517 										default:
518 											{
519 
520 												return TCL_ERROR;
521 											}
522 									}
523 
524 									i += 2;
525 								}
526 
527 								gdk_draw_pixbuf ( area->window, NULL, GDK_PIXBUF ( pixbuf ), src_x, src_y, dest_x, dest_y, width, height, dither, x_dither, y_dither );
528 
529 
530 							}
531 							break;
532 
533 						case SegmentsIdx:
534 							{
535 
536 								int k, n, nsegments, x1, y1, x2, y2;
537 								Tcl_ListObjLength ( interp, objv[3], &nsegments );
538 								g_print ( "drawing segments %s (%d)\n", Tcl_GetString ( objv[3] ), nsegments  );
539 								GtkWidget *childWidget;
540 								Tcl_Obj *tpx1, *tpy1, *tpx2, *tpy2;
541 
542 
543 								GdkSegment segments[nsegments];
544 								k = 0;
545 
546 								for ( n = 0; n < nsegments; n += 4 )
547 								{
548 
549 									g_print ( "n = %d\n", n );
550 
551 
552 									if ( Tcl_ListObjIndex ( interp,  objv[3], n, &tpx1 ) != TCL_OK )
553 									{
554 										return TCL_ERROR;
555 									}
556 
557 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 1, &tpy1 ) != TCL_OK )
558 									{
559 										return TCL_ERROR;
560 									}
561 
562 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 2, &tpx2 ) != TCL_OK )
563 									{
564 										return TCL_ERROR;
565 									}
566 
567 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 3, &tpy2 ) != TCL_OK )
568 									{
569 										return TCL_ERROR;
570 									}
571 
572 
573 									Tcl_GetIntFromObj ( interp, tpx1, &x1 );
574 									Tcl_GetIntFromObj ( interp, tpy1, &y1 );
575 									Tcl_GetIntFromObj ( interp, tpx2, &x2 );
576 									Tcl_GetIntFromObj ( interp, tpy2, &y2 );
577 
578 									segments[k].x1 = x1;
579 									segments[k].y1 = y1;
580 									segments[k].x2 = x2;
581 									segments[k].y2 = y2;
582 
583 									g_print ( "points = %d: item %d x1 = %d : y1 = %d : x2 = %d : y2 = %d\n", nsegments, k, x1, y1, x2, y2 );
584 									k++;
585 
586 								}
587 
588 								gdk_draw_segments ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], segments, nsegments / 4 );
589 
590 							}
591 							break;
592 						case RectangleIdx:
593 							{
594 								g_print ( "drawing rectangle %s\n", Tcl_GetString ( objv[3] ) );
595 								gint x, y, width, height;
596 								gint filled;
597 
598 								filled = 0;
599 
600 								sscanf ( Tcl_GetString ( objv[3] ), "%d %d %d %d", &x, &y, &width, &height );
601 
602 								int Idx3;
603 								static const char *rectOpts[] =
604 								{
605 									"-filled",
606 									NULL
607 								};
608 
609 								enum rectIdx
610 								{
611 									FilledIdx
612 								};
613 
614 								int i = 4;
615 
616 								while ( i < objc )
617 								{
618 									g_print ( "%d %d\n", i, objc );
619 									getIdx ( rectOpts, Tcl_GetString ( objv[i] ), &Idx3 );
620 
621 									switch ( Idx3 )
622 									{
623 										case FilledIdx:
624 											{
625 												g_print ( "yo\n" );
626 												Tcl_GetIntFromObj ( NULL, objv[i+1], &filled );
627 											}
628 											break;
629 										default: {};
630 									}
631 
632 									i += 2;
633 								}
634 
635 								gdk_draw_rectangle ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], filled, x, y, width, height );
636 
637 							} break;
638 						case ArcIdx:
639 							{
640 								g_print ( "drawing arc %s\n", Tcl_GetString ( objv[3] ) );
641 
642 
643 								gboolean filled;
644 								gint x, y;
645 								gint width, height;
646 								gint angle1, angle2;
647 
648 
649 								sscanf ( Tcl_GetString ( objv[3] ), "%d %d %d %d %d %D", &x, &y, &width, &height, &angle1, &angle2 );
650 
651 								int Idx4;
652 								static const char *arcOpts[] =
653 								{
654 									"-filled",
655 									NULL
656 								};
657 
658 								enum arcIdx
659 								{
660 									FilledIdx
661 								};
662 
663 								int i = 4;
664 
665 								while ( i < objc )
666 								{
667 									g_print ( "%d %d\n", i, objc );
668 									getIdx ( arcOpts, Tcl_GetString ( objv[i] ), &Idx4 );
669 
670 									switch ( Idx4 )
671 									{
672 										case FilledIdx:
673 											{
674 												Tcl_GetIntFromObj ( NULL, objv[i+1], &filled );
675 											}
676 											break;
677 										default: {};
678 									}
679 
680 									i += 2;
681 								}
682 
683 
684 								gdk_draw_arc ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], filled, x, y, width, height, angle1, angle2 );
685 
686 
687 							}
688 							break;
689 						case PolygonIdx:
690 							{
691 
692 								int k, n, npoints, x, y;
693 								gboolean filled;
694 								Tcl_ListObjLength ( interp, objv[3], &npoints );
695 								g_print ( "drawing polygon %s (%d)\n", Tcl_GetString ( objv[3] ), npoints  );
696 
697 
698 								GdkPoint points[npoints];
699 								k = 0;
700 
701 								for ( n = 0; n < npoints; n += 2 )
702 								{
703 									GtkWidget *childWidget;
704 									Tcl_Obj *tpx, *tpy;
705 
706 									if ( Tcl_ListObjIndex ( interp,  objv[3], n, &tpx ) != TCL_OK )
707 									{
708 										return TCL_ERROR;
709 									}
710 
711 									if ( Tcl_ListObjIndex ( interp,  objv[3], n + 1, &tpy ) != TCL_OK )
712 									{
713 										return TCL_ERROR;
714 									}
715 
716 									Tcl_GetIntFromObj ( interp, tpx, &x );
717 									Tcl_GetIntFromObj ( interp, tpy, &y );
718 
719 									g_print ( "points = %d: item %d x = %d : y = %d\n", npoints, k, x, y );
720 
721 									points[k].x = x;
722 									points[k].y = y;
723 									k++;
724 
725 								}
726 
727 
728 								int Idx5;
729 								static const char *polyOpts[] =
730 								{
731 									"-filled",
732 									NULL
733 								};
734 
735 								enum polyIdx
736 								{
737 									FilledIdx
738 								};
739 
740 								int i = 4;
741 
742 								while ( i < objc )
743 								{
744 									g_print ( "%d %d\n", i, objc );
745 									getIdx ( polyOpts, Tcl_GetString ( objv[i] ), &Idx5 );
746 
747 									switch ( Idx5 )
748 									{
749 										case FilledIdx:
750 											{
751 												Tcl_GetIntFromObj ( NULL, objv[i+1], &filled );
752 											}
753 											break;
754 										default: {};
755 									}
756 
757 									i += 2;
758 								}
759 
760 								//gdk_draw_points ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], points, npoints / 2 );
761 
762 								gdk_draw_polygon ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], filled, points, npoints / 2 );
763 
764 							} break;
765 						case TrapezoidsIdx:
766 							{
767 								/*
768 								double y1;	the y coordinate of the start point.
769 								double x11; the x coordinate of the top left corner
770 								double x21; the x coordinate of the top right corner
771 								double y2; 	the y coordinate of the end point.
772 								double x12; the x coordinate of the bottom left corner
773 								double x22; the x coordinate of the bottom right corner
774 								*/
775 
776 								int k, n, ntrapezoids;
777 								double y1, x11, x21, y2, x12, x22;
778 
779 								Tcl_ListObjLength ( interp, objv[3], &ntrapezoids );
780 								g_print ( "drawing polygon %s (%d)\n", Tcl_GetString ( objv[3] ), ntrapezoids  );
781 
782 								GdkTrapezoid trapezoids[ntrapezoids];
783 								k = 0;
784 
785 								for ( n = 0; n < ntrapezoids; n += 6 )
786 								{
787 									GtkWidget *childWidget;
788 									Tcl_Obj *tpy1, *tpx11, *tpx21, *tpy2, *tpx12, *tpx22;
789 
790 									Tcl_ListObjIndex ( interp,  objv[3], n, &tpy1 );
791 									Tcl_ListObjIndex ( interp,  objv[3], n + 1, &tpx11 );
792 									Tcl_ListObjIndex ( interp,  objv[3], n + 2, &tpx21 );
793 									Tcl_ListObjIndex ( interp,  objv[3], n + 3, &tpy2 );
794 									Tcl_ListObjIndex ( interp,  objv[3], n + 4 , &tpx12 );
795 									Tcl_ListObjIndex ( interp,  objv[3], n + 5, &tpx22 );
796 
797 
798 									Tcl_GetIntFromObj ( interp, tpy1, &y1 );
799 									Tcl_GetIntFromObj ( interp, tpx11, &x11 );
800 									Tcl_GetIntFromObj ( interp, tpx21, &x21 );
801 									Tcl_GetIntFromObj ( interp, tpy2, &y2 );
802 									Tcl_GetIntFromObj ( interp, tpx12, &x12 );
803 									Tcl_GetIntFromObj ( interp, tpx22, &x22 );
804 
805 									trapezoids[k].y1 = y1;
806 									trapezoids[k].x11 = x11;
807 									trapezoids[k].x21 = x21;
808 									trapezoids[k].y2 = y2;
809 									trapezoids[k].x12 = x12;
810 									trapezoids[k].x22 = x11;
811 
812 									k++;
813 
814 								}
815 
816 								gdk_draw_trapezoids ( area->window, area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], trapezoids, ntrapezoids / 2 );
817 
818 							} break;
819 						case GlyphIdx:
820 							{
821 								gint x, y;
822 								PangoGlyphString *glyphs;
823 								g_print ( "NOT YET IMPLEMENTED drawing glyph %s\n", Tcl_GetString ( objv[3] ) );
824 //gdk_draw_glyphs (GdkDrawable *drawable, GdkGC *gc, PangoFont *font, gint x, gint y, PangoGlyphString *glyphs);
825 
826 
827 
828 
829 
830 
831 							} break;
832 						case GlyphTransformedIdx:
833 							{
834 								g_print ( "NOT YET IMPLEMENTED  drawing glyphTransformed %s\n", Tcl_GetString ( objv[3] ) );
835 							} break;
836 						case LayoutLineIdx:
837 							{
838 								g_print ( "NOT YET IMPLEMENTED  drawing layoutLine %s\n", Tcl_GetString ( objv[3] ) );
839 							} break;
840 						case LayoutWithColorsIdx:
841 							{
842 								g_print ( "NOT YET IMPLEMENTED  drawing layoutWithColors %s\n", Tcl_GetString ( objv[3] ) );
843 							} break;
844 						case StringIdx:
845 							{
846 								g_print ( "drawing string %s\n", Tcl_GetString ( objv[3] ) );
847 
848 								GdkFont *font;
849 								GdkGC *gc;
850 								gint x;
851 								gint y;
852 								const gchar *string;
853 								/*
854 								typedef struct {
855 								  GdkFontType type;
856 								  gint ascent;
857 								  gint descent;
858 								} GdkFont;
859 								*/
860 
861 								font = gdk_font_load ( "-adobe-helvetica-medium-r-normal--*-120-*-*-*-*-*-*" );
862 								x = 100;
863 								y = 100;
864 								string = "Hello World!";
865 
866 
867 								int Idx3;
868 								static const char *rectOpts[] =
869 								{
870 									"-string", "-font",
871 									"-x", "-y",
872 									NULL
873 								};
874 
875 								enum rectIdx
876 								{
877 									StringIdx, FontIdx, XIdx, YIdx
878 								};
879 
880 								int i = 4;
881 
882 								while ( i < objc )
883 								{
884 									g_print ( "%d %d\n", i, objc );
885 									getIdx ( rectOpts, Tcl_GetString ( objv[i] ), &Idx3 );
886 
887 									switch ( Idx3 )
888 									{
889 										case StringIdx:
890 											{
891 												g_print ( "yo\n" );
892 												string = Tcl_GetString ( objv[i+1] );
893 											}
894 											break;
895 										case FontIdx:
896 											{
897 												g_print ( "yo\n" );
898 												string = Tcl_GetString ( objv[i+1] );
899 											}
900 											break;
901 										case XIdx:
902 											{
903 												g_print ( "yo\n" );
904 												Tcl_GetIntFromObj ( NULL, objv[i+1], &x );
905 											}
906 											break;
907 										case YIdx:
908 											{
909 												g_print ( "yo\n" );
910 												Tcl_GetIntFromObj ( NULL, objv[i+1], &y );
911 											}
912 											break;
913 										default: {};
914 									}
915 
916 									i += 2;
917 								}
918 
919 								gdk_draw_string ( area->window, font,  area->style->fg_gc[GTK_WIDGET_STATE ( area ) ], x, y, Tcl_GetString ( objv[3] ) );
920 
921 							} break;
922 						case TextIdx:
923 							{
924 								g_print ( "drawing text %s\n", Tcl_GetString ( objv[3] ) );
925 								/*
926 									char *fnt = Tcl_GetStringFromObj ( opt->val.obj, NULL );
927 									PangoFontDescription *font_desc = pango_font_description_from_string ( fnt );
928 
929 									gtk_widget_modify_font ( GTK_WIDGET ( obj ), font_desc );
930 									pango_font_description_free ( font_desc );
931 								*/
932 
933 							} break;
934 						case ImageIdx:
935 							{
936 								g_print ( "NOT YET IMPLEMENTED  drawing image %s\n", Tcl_GetString ( objv[3] ) );
937 							} break;
938 						default:
939 							{
940 								g_print ( "drawing defaul %s\n", Tcl_GetString ( objv[3] ) );
941 							}
942 					}
943 				}
944 				break;
945 			default: {}
946 			}
947 	}
948 
949 
950 
951 	return TCL_OK;
952 }
953 
954 
955 /**
956 /brief
957 **/
gnoclDrawingAreaCmd(ClientData data,Tcl_Interp * interp,int objc,Tcl_Obj * const objv[])958 int gnoclDrawingAreaCmd ( ClientData data, Tcl_Interp *interp, int objc,	Tcl_Obj * const objv[] )
959 {
960 	if ( gnoclGetCmdsAndOpts ( interp, cmds, drawingAreaOptions, objv, objc ) == TCL_OK )
961 	{
962 		return TCL_OK;
963 	}
964 
965 	int       ret;
966 	GtkWidget *widget;
967 
968 	if ( gnoclParseOptions ( interp, objc, objv, drawingAreaOptions ) != TCL_OK )
969 	{
970 		gnoclClearOptions ( drawingAreaOptions );
971 		return TCL_ERROR;
972 	}
973 
974 	widget = gtk_drawing_area_new ();
975 	gtk_widget_set_can_focus ( widget, 1 );	// allow widget to receive keyboard events
976 
977 	gtk_widget_show ( GTK_WIDGET ( widget ) );
978 
979 	gnoclSetOptions ( interp, drawingAreaOptions, G_OBJECT ( widget ), -1 );
980 
981 	gnoclClearOptions ( drawingAreaOptions );
982 
983 
984 	/* register the new widget for use with the Tcl interpretor */
985 	return gnoclRegisterWidget ( interp, GTK_WIDGET ( widget ), drawingAreaFunc );
986 
987 }
988 
989 /**
990 \brief      Add new settings to the widget option array.
991 \author     William J Giddings
992 \date       19/Feb/2010
993 \since      0.9.94
994 \see        http://library.gnome.org/devel/gdk/stable/gdk-Events.html
995 \note       Event Mask Options:
996 
997       GDK_EXPOSURE_MASK         GDK_POINTER_MOTION_MASK     GDK_POINTER_MOTION_HINT_MASK
998       GDK_BUTTON_MOTION_MASK    GDK_BUTTON1_MOTION_MASK     GDK_BUTTON2_MOTION_MASK
999       GDK_BUTTON3_MOTION_MASK   GDK_BUTTON_PRESS_MASK       GDK_BUTTON_RELEASE_MASK
1000       GDK_KEY_PRESS_MASK        GDK_KEY_RELEASE_MASK        GDK_ENTER_NOTIFY_MASK
1001       GDK_LEAVE_NOTIFY_MASK     GDK_FOCUS_CHANGE_MASK       GDK_STRUCTURE_MASK
1002       GDK_PROPERTY_CHANGE_MASK  GDK_VISIBILITY_NOTIFY_MASK  GDK_PROXIMITY_IN_MASK
1003       GDK_PROXIMITY_OUT_MASK    GDK_SUBSTRUCTURE_MASK       GDK_SCROLL_MASK
1004       GDK_ALL_EVENTS_MASK
1005 
1006 **/
doOptionAdd(Tcl_Interp * interp,GtkWidget * area,gint OptIdx)1007 int doOptionAdd ( Tcl_Interp *interp, GtkWidget *area, gint OptIdx )
1008 {
1009 #ifdef DEBUG_DRAWING_AREA
1010 	g_print ( "drawingArea OptionIdx = %s\n", options[OptIdx] );
1011 #endif
1012 
1013 
1014 	/* return error the maximum number of options has been reached */
1015 	gint j = sizeof ( drawingAreaOptions ) / sizeof ( GnoclOption );
1016 
1017 	if ( j == _n )
1018 	{
1019 		return TCL_ERROR;
1020 	}
1021 
1022 	/* set the option name directly from list of possible options */
1023 	drawingAreaOptions[_n].optName = options[OptIdx];
1024 
1025 	/* set the remaining values, assign callback function */
1026 	switch ( OptIdx )
1027 	{
1028 		case OnExposeIdx:
1029 			{
1030 				//g_print ( "adding GDK_EXPOSURE_MASK OptIdx = %d\n", OptIdx );
1031 				gtk_widget_add_events ( area, GDK_EXPOSURE_MASK );
1032 				drawingAreaOptions[_n].func = gnoclOptOnExpose;
1033 			} break;
1034 
1035 		case OnButton1MotionIdx:
1036 			{
1037 				//g_print ( "adding GDK_BUTTON1_MOTION_MASK OptIdx = %d\n", OptIdx );
1038 				gtk_widget_add_events ( area, GDK_BUTTON1_MOTION_MASK );
1039 				drawingAreaOptions[_n].func = gnoclOptOnKeyPress;
1040 			} break;
1041 
1042 		case OnButton2MotionIdx:
1043 			{
1044 				//g_print ( "adding GDK_BUTTON2_MOTION_MASK OptIdx = %d\n", OptIdx );
1045 				gtk_widget_add_events ( area, GDK_BUTTON2_MOTION_MASK );
1046 				drawingAreaOptions[_n].func = gnoclOptOnKeyPress;
1047 			} break;
1048 
1049 		case OnButton3MotionIdx:
1050 			{
1051 				//g_print ( "adding GDK_BUTTON1_MOTION_MASK OptIdx = %d\n", OptIdx );
1052 				gtk_widget_add_events ( area, GDK_BUTTON2_MOTION_MASK );
1053 				drawingAreaOptions[_n].func = gnoclOptOnKeyPress;
1054 			} break;
1055 
1056 		case OnKeyPressIdx:
1057 			{
1058 				//g_print ( "adding GDK_KEY_PRESS_MASK OptIdx = %d\n", OptIdx );
1059 				gtk_widget_add_events ( area, GDK_KEY_PRESS_MASK );
1060 				drawingAreaOptions[_n].func = gnoclOptOnKeyPress;
1061 			} break;
1062 
1063 		case OnKeyReleaseIdx:
1064 			{
1065 				//g_print ( "adding GDK_KEY_RELEASE_MASK OptIdx = %d\n", OptIdx );
1066 				gtk_widget_add_events ( area, GDK_KEY_RELEASE_MASK );
1067 				drawingAreaOptions[_n].func = gnoclOptOnKeyRelease;
1068 			}
1069 			break;
1070 
1071 		case OnButtonMotionIdx:
1072 			{
1073 				//g_print ( "adding GDK_BUTTON_MOTION_MASK OptIdx = %d\n", OptIdx );
1074 				gtk_widget_add_events ( area, GDK_BUTTON_MOTION_MASK );
1075 				drawingAreaOptions[_n].func = gnoclOptOnButtonMotion;
1076 			}
1077 			break;
1078 
1079 		case OnPointerMotionIdx: // working ok!
1080 			{
1081 				//g_print ( "adding GDK_POINTER_MOTION_MASK  OptIdx = %d\n", OptIdx );
1082 				gtk_widget_add_events ( area, GDK_POINTER_MOTION_MASK );
1083 				drawingAreaOptions[_n].func = gnoclOptOnMotion;
1084 			}
1085 			break;
1086 
1087 		case OnEnterIdx: // working ok!
1088 			{
1089 				//g_print ( "adding GDK_ENTER_NOTIFY_MASK  OptIdx = %d\n", OptIdx );
1090 				gtk_widget_add_events ( area, GDK_ENTER_NOTIFY_MASK );
1091 				drawingAreaOptions[_n].propName = "E";
1092 				drawingAreaOptions[_n].func = gnoclOptOnEnterLeave;
1093 			}
1094 			break;
1095 
1096 		case OnLeaveIdx: // working ok!
1097 			{
1098 				//g_print ( "adding GDK_ENTER_NOTIFY_MASK  OptIdx = %d\n", OptIdx );
1099 				gtk_widget_add_events ( area, GDK_LEAVE_NOTIFY_MASK );
1100 				drawingAreaOptions[_n].propName = "L";
1101 				drawingAreaOptions[_n].func = gnoclOptOnEnterLeave;
1102 			}
1103 			break;
1104 		case OnButtonPressIdx: // working ok!
1105 			{
1106 				//g_print ( "adding GDK_BUTTON_PRESS_MASK  OptIdx = %d\n", OptIdx );
1107 				gtk_widget_add_events ( area, GDK_BUTTON_PRESS_MASK ) ;
1108 				drawingAreaOptions[_n].propName = "P";
1109 				drawingAreaOptions[_n].func = gnoclOptOnButton;
1110 			}
1111 			break;
1112 
1113 		case OnButtonReleaseIdx: // working ok!
1114 			{
1115 				//g_print ( "adding GDK_BUTTON_RELEASE_MASK  OptIdx = %d\n", OptIdx );
1116 				gtk_widget_add_events ( area, GDK_BUTTON_RELEASE_MASK ) ;
1117 				drawingAreaOptions[_n].propName = "R";
1118 				drawingAreaOptions[_n].func = gnoclOptOnButton;
1119 			}
1120 			break;
1121 	}
1122 
1123 	/* implement changes */
1124 	gnoclSetOptions ( interp, drawingAreaOptions, area, -1 );
1125 
1126 	return ++_n;
1127 }
1128 
1129