source: gs2-extensions/music-stand/trunk/src/scribble-simple/scribble-simple.c@ 22562

Last change on this file since 22562 was 22562, checked in by davidb, 14 years ago
File size: 19.9 KB
Line 
1
2/* GTK - The GIMP Toolkit
3 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21#include <stdlib.h>
22#include <stdio.h>
23#include <gtk/gtk.h>
24#include <gdk/gdkkeysyms.h>
25#include <glib/gstdio.h>
26#include <string.h>
27
28/* Backing pixmap for drawing area */
29static GdkPixmap *pixmap = NULL;
30
31//buffer pixmap which will be drawn into the pixmap drawn on screen
32static GdkPixmap *buffer_pixmap = NULL;
33
34//point data to be added to an appropriate file upon leaving the relevant page [or exiting?]
35static GList *points_list = NULL;
36
37//static char *folder_name = "chopin_prelude_op45-a4";
38static int current_page = 0;
39static int prev_page = 0;
40
41static int vert_page_progress = 0;
42static int hori_page_progress = 0;
43
44//percentage of height at which we change from uncovering vertically to horizontally
45static int change_height_percent=80;
46
47static GdkPixbuf *pp_pbuf_image = NULL;
48static GdkGC* pp_gc = NULL;
49
50static int pp_width = 0;
51static int pp_height = 0;
52
53static int page_width = 0;
54static int page_height = 0;
55
56//for tracking mouse movement
57static int last_x_pos = -1;
58static int last_y_pos = -1;
59
60
61static gboolean in_progress = FALSE;
62
63static gboolean load_show_page( GtkWidget *widget,
64 char *folder_name,
65 int page_number);
66
67static gboolean load_show_page_immediate( GtkWidget *widget,
68 char *folder_name,
69 int page_number);
70
71static gboolean read_point_data_from_file (GtkWidget *widget,
72 GdkPixmap *drawing_pixmap,
73 char *filename);
74
75
76static guint timeout_id = 0;
77
78
79static gboolean update_progress_page(gpointer data)
80{
81 GtkWidget* widget = (GtkWidget*)data;
82
83 g_print("updating page progress = %d\n", vert_page_progress);
84
85 if (vert_page_progress < 100)
86 {
87 if (vert_page_progress < change_height_percent)
88 {
89 vert_page_progress+=10;
90
91 int update_height = (int)(pp_height * (vert_page_progress / 100.0));
92
93// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image,
94// 0, 0, 0, 0, -1, update_height, GDK_RGB_DITHER_NONE, 0, 0);
95
96 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
97 0, 0, 0, 0, -1, update_height);
98
99 gtk_widget_queue_draw_area (widget,
100 0, 0,
101 pp_width, update_height);
102 return TRUE;
103 }
104 else
105 {
106 //update horizontally
107 if (hori_page_progress < 100)
108 {
109
110 hori_page_progress+=10;
111
112 int update_height = (int)(pp_height * (vert_page_progress / 100.0));
113 int update_width = (int)(pp_width * (hori_page_progress / 100.0));
114
115// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image,
116// 0, update_height, 0, update_height, update_width, pp_height - update_height, GDK_RGB_DITHER_NONE, 0, 0);
117
118 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
119 0, update_height, 0, update_height, update_width, pp_height - update_height);
120
121 gtk_widget_queue_draw_area (widget,
122 0, 0,
123 update_width, pp_height);
124
125 return TRUE;
126
127 }
128 else
129 {
130 //reset values
131// vert_page_progress = 0;
132// hori_page_progress = 0;
133 in_progress = FALSE;
134
135
136
137 return FALSE;
138 }
139 }
140 }
141
142 else
143 {
144
145 //reset values
146// vert_page_progress = 0;
147// hori_page_progress = 0;
148 in_progress = FALSE;
149 return FALSE;
150 }
151
152}
153
154
155/* Create a new backing pixmap of the appropriate size */
156static gboolean configure_event( GtkWidget *widget,
157 GdkEventConfigure *event,
158 gpointer folder_name )
159{
160
161// char *filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page00.tif";
162// char *filename = "page1.tif";
163
164 if (pixmap)
165 g_object_unref (pixmap);
166
167 pixmap = gdk_pixmap_new (widget->window,
168 widget->allocation.width,
169 widget->allocation.height,
170 -1);
171
172 buffer_pixmap = gdk_pixmap_new (widget->window,
173 widget->allocation.width,
174 widget->allocation.height,
175 -1);
176
177
178 gdk_draw_rectangle (pixmap,
179 widget->style->black_gc,
180 TRUE,
181 0, 0,
182 widget->allocation.width,
183 widget->allocation.height);
184
185
186 pp_gc = gdk_gc_new (pixmap);
187
188 //reset values
189 vert_page_progress = 0;
190 hori_page_progress = 0;
191 in_progress = TRUE;
192 load_show_page_immediate (widget, (char*)folder_name, 0);
193
194 return TRUE;
195}
196
197/* Redraw the screen from the backing pixmap */
198static gboolean expose_event( GtkWidget *widget,
199 GdkEventExpose *event )
200{
201 gdk_draw_drawable (widget->window,
202 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
203 pixmap,
204 event->area.x, event->area.y,
205 event->area.x, event->area.y,
206 event->area.width, event->area.height);
207
208 return FALSE;
209}
210
211
212
213
214#define min2(x,y) (x<y)?x:y
215#define max2(x,y) (x>y)?x:y
216//connecting line
217static void draw_connecting_line (GtkWidget *widget,
218 GdkPixmap *drawing_pixmap,
219 gdouble last_x,
220 gdouble last_y,
221 gdouble x,
222 gdouble y)
223{
224 //we are going to draw a line between two points instead of just drawing the next point
225 gdk_gc_set_line_attributes ( widget->style->black_gc,
226 2, GDK_LINE_SOLID,
227 GDK_CAP_BUTT, GDK_JOIN_ROUND);
228
229 gdk_draw_line ( drawing_pixmap,
230 widget->style->black_gc,
231 last_x, last_y,
232 x, y);
233
234 int x_min = min2(x, last_x);
235 int y_min = min2(y, last_y);
236 int x_max = max2(x, last_x);
237 int y_max = max2(y, last_y);
238
239 gtk_widget_queue_draw_area ( widget,
240 x_min - 2, y_min - 2,
241 x_max - x_min + 5, y_max - y_min + 5);
242}
243
244/* Draw a rectangle on the screen */
245static void draw_brush( GtkWidget *widget,
246 GdkPixmap *drawing_pixmap,
247 gdouble x,
248 gdouble y)
249{
250 GdkRectangle update_rect;
251
252 update_rect.x = x - 2;
253 update_rect.y = y - 2;
254 update_rect.width = 4;
255 update_rect.height = 4;
256 gdk_draw_rectangle (drawing_pixmap,
257 widget->style->black_gc,
258 TRUE,
259 update_rect.x, update_rect.y,
260 update_rect.width, update_rect.height);
261 gtk_widget_queue_draw_area (widget,
262 update_rect.x, update_rect.y,
263 update_rect.width, update_rect.height);
264}
265
266
267
268static gboolean file_exists (char *filename)
269{
270 //if NULL is returned then the file probably does not exist; return false
271 if (g_fopen(filename, "r") == NULL) return FALSE;
272 return TRUE;
273}
274
275static gboolean load_show_page( GtkWidget *widget,
276 char *folder_name,
277 int page_number)
278{
279
280
281 char filename[512];
282 sprintf(filename, "%s/%s-page%02d.tif", folder_name, folder_name, page_number);
283
284
285 g_print("%s\n\n", filename);
286
287
288// filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page01.tif";
289
290
291 if (!file_exists(filename)) return FALSE;
292
293
294 //get the percentage of page to load/display before swapping from vertical loading to horizontal loading
295 char filename_pagebreak[512];
296 sprintf (filename_pagebreak, "%s.pagebreak", filename);
297 if (file_exists(filename_pagebreak)) {
298 FILE *file = fopen(filename_pagebreak, "r");
299 char line_buf[10]; //shouldn't be longer than 2 characters, really
300 fgets(line_buf, 10, file);
301 change_height_percent = atoi ( line_buf );
302 }
303 else
304 {
305 change_height_percent = 80; //defaults to 80% if there is no pagebreak file
306 }
307 g_print("change_height_percent: %d\n", change_height_percent);
308
309
310
311 // Get the origial image size.
312 gdk_pixbuf_get_file_info(filename, &pp_width, &pp_height);
313 page_width = widget->allocation.width;
314 page_height = widget->allocation.height;
315
316 gdk_drawable_get_size(pixmap, &page_width, &page_height);
317
318//getting the scaled sizes to load the image in at fullscreen
319 int w = pp_width;
320 int h = pp_height;
321 double scale = 1;
322 if (pp_width >= pp_height)
323 {
324 if (pp_width != page_width)
325 {
326 scale = (double)pp_width / (double)page_width;
327 }
328 }
329 else if (pp_height > pp_width)
330 {
331 if (pp_height != page_height)
332 {
333 scale = (double)pp_height / (double)page_height;
334 }
335 }
336 w = (int)((double)pp_width / scale);
337 h = (int)((double)pp_height / scale)- 1;
338 pp_width = w;
339 pp_height = h;
340
341 pp_pbuf_image = gdk_pixbuf_new_from_file_at_size(filename, pp_width, pp_height, 0);
342
343 gdk_draw_pixbuf (buffer_pixmap, pp_gc, pp_pbuf_image,
344 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
345
346//drawing the point/scribble data onto the buffer pixmap
347 char point_filename[512];
348 sprintf(point_filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, page_number);
349 read_point_data_from_file(widget, buffer_pixmap, point_filename);
350
351
352
353
354 //pp_gc = gdk_gc_new (pixmap);
355
356
357
358
359 //reset values
360 vert_page_progress = 0;
361 hori_page_progress = 0;
362 timeout_id = g_timeout_add (1000, update_progress_page, widget);
363
364 return TRUE;
365
366}
367
368
369
370static gboolean load_show_page_immediate( GtkWidget *widget,
371 char *folder_name,
372 int page_number)
373{
374
375
376 char filename[512];
377 sprintf(filename, "%s/%s-page%02d.tif", folder_name, folder_name, page_number);
378
379
380 g_print("%s\n\n", filename);
381
382
383// filename = "chopin_prelude_op45-a4/chopin_prelude_op45-a4-page01.tif";
384
385
386 if (!file_exists(filename)) return FALSE;
387
388
389
390 // Get the origial image size.
391 gdk_pixbuf_get_file_info(filename, &pp_width, &pp_height);
392 page_width = widget->allocation.width;
393 page_height = widget->allocation.height;
394
395 gdk_drawable_get_size(pixmap, &page_width, &page_height);
396
397//getting the scaled sizes to load the image in at fullscreen
398 int w = pp_width;
399 int h = pp_height;
400 double scale = 1;
401 if (pp_width >= pp_height)
402 {
403 if (pp_width != page_width)
404 {
405 scale = (double)pp_width / (double)page_width;
406 }
407 }
408 else if (pp_height > pp_width)
409 {
410 if (pp_height != page_height)
411 {
412 scale = (double)pp_height / (double)page_height;
413 }
414 }
415 w = (int)((double)pp_width / scale);
416 h = (int)((double)pp_height / scale)- 1;
417 pp_width = w;
418 pp_height = h;
419
420 pp_pbuf_image = gdk_pixbuf_new_from_file_at_size(filename, pp_width, pp_height, 0);
421
422 //pp_gc = gdk_gc_new (pixmap);
423
424
425
426 //reset values
427 vert_page_progress = 0;
428 hori_page_progress = 0;
429
430
431
432
433
434 gdk_draw_pixbuf (buffer_pixmap, pp_gc, pp_pbuf_image,
435 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
436
437//drawing the point/scribble data onto the buffer pixmap
438 char point_filename[512];
439 sprintf(point_filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, page_number);
440 read_point_data_from_file(widget, buffer_pixmap, point_filename);
441
442
443
444//current
445
446
447 gdk_draw_drawable (pixmap, pp_gc, buffer_pixmap,
448 0, 0, 0, 0, -1, -1);
449
450// gdk_draw_pixbuf (pixmap, pp_gc, pp_pbuf_image, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NONE, 0, 0);
451
452 gtk_widget_queue_draw_area (widget,
453 0, 0,
454 pp_width, pp_height);
455
456
457
458
459
460// g_timeout_add (1000, update_progress_page, widget);
461
462 in_progress = FALSE;
463
464 return TRUE;
465
466}
467
468
469
470
471
472static gboolean write_point_data_to_file ( char *filename)
473{
474 FILE *file;
475 file = fopen(filename, "w+");
476
477 GList *curr = points_list;
478 while (curr != NULL)
479 {
480 g_print("writing: %s\n", (char*)curr->data);
481 fprintf(file, "%s\n", (char*)curr->data);
482 curr = g_list_next(curr);
483 }
484
485 fclose(file);
486
487 return TRUE;
488}
489
490static gboolean read_point_data_from_file (GtkWidget *widget,
491 GdkPixmap *drawing_pixmap,
492 char *filename)
493{
494 FILE *file;
495 file = fopen(filename, "r+");
496 if (file == NULL)
497 {
498 g_print ("no point file data\n");
499 return FALSE;
500 }
501 int old_x_val, old_y_val, x_val, y_val;
502 gboolean start_line = TRUE;
503// while (feof(file) == 0)
504 g_print("gonna scan us some file: %s\n", filename);
505
506
507 //reset points list
508 points_list = NULL;
509 while (fscanf(file, "%d %d\n", &x_val, &y_val) != EOF)
510 {
511 //add this data to the list of point data, ...
512 char *data = malloc(16);
513 if (data == NULL)
514 {
515 fprintf(stderr, "error (failed to allocate memory in button_press_event");
516 exit(-1);
517 }
518 sprintf (data, "%d %d", x_val, y_val);
519 points_list = g_list_append(points_list, data);
520
521 g_print("%s\n", data);
522//break;
523// fscanf(file, "%d %d\n", &x_val, &y_val);
524 if (x_val == -1) //then continue;
525 {
526 start_line = TRUE;
527 continue;
528 }
529 else if (start_line)
530 {
531 draw_brush(widget, drawing_pixmap, x_val, y_val);
532 old_x_val = x_val;
533 old_y_val = y_val;
534 }
535 else
536 {
537 draw_connecting_line (widget, drawing_pixmap, old_x_val, old_y_val, x_val, y_val);
538 old_x_val = x_val;
539 old_y_val = y_val;
540 }
541
542 start_line = FALSE;
543 }
544 fclose(file);
545 return TRUE;
546}
547
548
549static gboolean button_release_event( GtkWidget *widget,
550 GdkEventButton *event)
551{
552 g_print("mouse released\n");
553 last_x_pos = -1;
554 last_y_pos = -1;
555
556 //add this gap to the list of point data, ...
557 points_list = g_list_append(points_list, "-1 -1");
558
559 return TRUE;
560}
561
562
563static gboolean button_press_event( GtkWidget *widget,
564 GdkEventButton *event,
565 gpointer folder_name)
566{
567
568
569 if (event->button == 1 && pixmap != NULL)
570 {
571 if (!in_progress)
572 {
573 draw_brush (widget, pixmap, event->x, event->y);
574 last_x_pos = event->x;
575 last_y_pos = event->y;
576
577 //add this data to the list of point data, ...
578 char *data = malloc(16);
579 if (data == NULL)
580 {
581 fprintf(stderr, "error (failed to allocate memory in button_press_event");
582 exit(-1);
583 }
584 sprintf (data, "%d %d", (int)event->x, (int)event->y);
585 points_list = g_list_append(points_list, data);
586
587 //g_print("%x\n", folder_name);
588
589 //in_progress = TRUE;
590
591 //current_page += 1;
592 //load_show_page (widget, (char*)folder_name, current_page);
593 }
594 else
595 {
596 g_print("in progress so can't draw\n");
597 }
598 }
599
600 return TRUE;
601}
602
603
604static gboolean key_press_event( GtkWidget *widget,
605 GdkEventKey *event,
606 gpointer data_list)
607{
608
609if (event->type == GDK_KEY_RELEASE) return TRUE;
610
611GtkWidget *drawing_area = (GtkWidget*)g_list_nth_data(data_list, 0);
612char *folder_name = (char*)g_list_nth_data(data_list, 1);
613
614g_print("called keypress event\n");
615 if (!in_progress)
616 {
617 g_print("NOT inprogress\n");
618 //write the point data for this page to a file
619 char filename[512];
620 sprintf(filename, "%s/%s-page%02d.tif.pointdata", folder_name, folder_name, current_page);
621 g_print("writing to file: %s", filename);
622 write_point_data_to_file (filename);
623
624 switch (event->keyval)
625 {
626 case GDK_Right:
627 printf("right!\n");
628 prev_page = current_page;
629 current_page += 1;
630 break;
631 case GDK_Left:
632 printf("left!\n");
633 prev_page = current_page;
634 current_page -= 1;
635 break;
636 default:
637 return TRUE;
638 }
639 in_progress = TRUE;
640 load_show_page (drawing_area, folder_name, current_page);
641 }
642 else //in progress, so speed up that progress: load page immediately
643 {
644 g_print("in progress\n");
645 switch (event->keyval)
646 {
647 case GDK_Right:
648 g_source_remove(timeout_id);
649 if (current_page != prev_page+1)
650 {
651 current_page = prev_page;
652 }
653 load_show_page_immediate(drawing_area, folder_name, current_page);
654// printf("right!\n");
655// current_page += 1;
656 break;
657 case GDK_Left:
658 g_source_remove(timeout_id);
659 if (current_page != prev_page-1)
660 {
661 current_page = prev_page;
662 }
663 load_show_page_immediate(drawing_area, folder_name, current_page);
664// printf("left!\n");
665// current_page -= 1;
666 break;
667 default:
668 return TRUE;
669 }
670
671// load_show_page_immediate(drawing_area, folder_name, current_page);
672 }
673
674 return TRUE;
675}
676
677static gboolean motion_notify_event( GtkWidget *widget,
678 GdkEventMotion *event )
679{
680 int x, y;
681 GdkModifierType state;
682
683 if (event->is_hint)
684 gdk_window_get_pointer (event->window, &x, &y, &state);
685 else
686 {
687 x = event->x;
688 y = event->y;
689 state = event->state;
690 }
691
692 if (state & GDK_BUTTON1_MASK && pixmap != NULL)
693 {
694 if (!in_progress)
695 {
696 //if we haven't set x yet, don't do this
697 if (last_x_pos == -1) return TRUE;
698
699 draw_connecting_line (widget, pixmap, last_x_pos, last_y_pos, x, y);
700
701 last_x_pos = x;
702 last_y_pos = y;
703
704
705
706 //add this data to the list of point data, ...
707 char *data = malloc(16);
708 if (data == NULL)
709 {
710 fprintf(stderr, "error (failed to allocate memory in button_press_event");
711 exit(-1);
712 }
713 sprintf (data, "%d %d", (int)event->x, (int)event->y);
714 points_list = g_list_append(points_list, data);
715
716
717// draw_brush (widget, x, y);
718 }
719
720 }
721
722 return TRUE;
723}
724
725void quit ()
726{
727 exit (0);
728}
729
730int main( int argc,
731 char *argv[] )
732{
733
734char *folder_name;
735
736 if (argc == 1)
737 {
738 //default
739 folder_name = "chopin_prelude_op45-a4";
740 }
741 else
742 {
743 folder_name = argv[1];
744 }
745
746
747//************************************
748/*
749FILE *writing;
750//int buffer = 256;
751int value = 6;
752char *filename;
753filename = "file.txt";
754writing = fopen(filename, "w+");
755fprintf(writing, "%d\n", value);
756value = 7;
757fprintf(writing, "%d\n", value);
758value = 8;
759fprintf(writing, "%d\n", value);
760fclose(writing);
761
762int blah = 0;
763writing = fopen(filename, "r+");
764fscanf(writing, "%d\n", &blah);
765g_print("%d\n", blah);
766fscanf(writing, "%d\n", &blah);
767g_print("%d\n", blah);
768fscanf(writing, "%d\n", &blah);
769g_print("%d\n", blah);
770fclose(writing);
771*/
772//************************************
773
774
775 GtkWidget *window;
776 GtkWidget *drawing_area;
777 GtkWidget *vbox;
778
779 GtkWidget *button;
780
781 gtk_init (&argc, &argv);
782
783 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
784 gtk_widget_set_name (window, "Test Input");
785
786 vbox = gtk_vbox_new (FALSE, 0);
787 gtk_container_add (GTK_CONTAINER (window), vbox);
788 gtk_widget_show (vbox);
789
790 g_signal_connect (window, "destroy",
791 G_CALLBACK (quit), NULL);
792
793 /* Create the drawing area */
794
795 drawing_area = gtk_drawing_area_new ();
796 gtk_widget_set_size_request (GTK_WIDGET (drawing_area), 200, 200);
797 gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
798
799 gtk_widget_show (drawing_area);
800
801 /* Signals used to handle backing pixmap */
802
803 g_signal_connect (drawing_area, "expose-event",
804 G_CALLBACK (expose_event), NULL);
805 g_signal_connect (drawing_area,"configure-event",
806 G_CALLBACK (configure_event), folder_name);
807
808 /* Event signals */
809
810 g_signal_connect (drawing_area, "motion-notify-event",
811 G_CALLBACK (motion_notify_event), NULL);
812 g_signal_connect (drawing_area, "button-press-event",
813 G_CALLBACK (button_press_event), folder_name);
814 g_signal_connect (drawing_area, "button-release-event",
815 G_CALLBACK (button_release_event), NULL);
816
817 //needs to be passed both the drawing_area, and the folder_name, so create a glist and pass a pointer to that
818 GList *key_press_data = NULL;
819 key_press_data = g_list_append(key_press_data, drawing_area);
820 key_press_data = g_list_append(key_press_data, folder_name);
821
822 g_signal_connect (window, "key-press-event",
823 G_CALLBACK (key_press_event), key_press_data);
824
825
826 gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
827 | GDK_LEAVE_NOTIFY_MASK
828 | GDK_BUTTON_PRESS_MASK
829 | GDK_BUTTON_RELEASE_MASK
830 | GDK_POINTER_MOTION_MASK
831 | GDK_POINTER_MOTION_HINT_MASK);
832
833 /* .. And a quit button */
834 button = gtk_button_new_with_label ("Quit");
835 gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
836
837 g_signal_connect_swapped (button, "clicked",
838 G_CALLBACK (gtk_widget_destroy),
839 window);
840 gtk_widget_show (button);
841
842 gtk_widget_show (window);
843
844 gtk_main ();
845
846 return 0;
847}
Note: See TracBrowser for help on using the repository browser.