]> git.cworth.org Git - scherzo/blob - scherzo.c
Start drawing some very rudimentary notes.
[scherzo] / scherzo.c
1 /* scherzo - Music notation training
2  *
3  * Copyright © 2010 Carl Worth
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program 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
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see http://www.gnu.org/licenses/ .
17  */
18
19 #include <gtk/gtk.h>
20 #include <gdk/gdkkeysyms.h>
21
22 #include "score.h"
23
24 #define unused(foo) foo __attribute__((unused))
25
26 typedef struct scherzo
27 {
28     score_t *score;
29     int staff_height;
30 } scherzo_t;
31
32 static int
33 on_delete_event_quit (unused (GtkWidget *widget),
34                       unused (GdkEvent *event),
35                       unused (gpointer user_data))
36 {
37     gtk_main_quit ();
38
39     /* Returning FALSE allows the default handler for delete-event
40      * to proceed to cleanup the widget. */
41     return FALSE;
42 }
43
44 static int
45 on_expose_event_draw (GtkWidget *widget,
46                       unused (GdkEventExpose *expose),
47                       void * user_data)
48 {
49     scherzo_t *scherzo = user_data;
50     score_t *score = scherzo->score;
51     cairo_t *cr;
52     GtkAllocation allocation;
53     static const int pad = 10;
54     int widget_width;
55
56     gtk_widget_get_allocation (widget, &allocation);
57     widget_width = allocation.width;
58
59     cr = gdk_cairo_create (widget->window);
60
61     /* White background */
62     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
63     cairo_paint (cr);
64
65     /* Add some padding on the sides and top */
66     cairo_translate (cr, pad, (int) scherzo->staff_height / 2);
67     score_set_staff_height (score, scherzo->staff_height);
68     score_set_width (score, widget_width - 2 * pad);
69
70     score_draw (score, cr);
71  
72     return TRUE;
73 }
74
75 static int
76 on_key_press_event (GtkWidget *widget,
77                     GdkEventKey *key,
78                     void *user_data)
79 {
80     scherzo_t *scherzo = user_data;
81
82     switch (key->keyval) {
83     case GDK_KEY_plus:
84     case GDK_KEY_KP_Add:
85     case GDK_KEY_equal:
86     case GDK_KEY_KP_Equal:
87         scherzo->staff_height += 4;
88         gtk_widget_queue_draw (widget);
89         return TRUE;
90         break;
91     case GDK_KEY_minus:
92     case GDK_KEY_KP_Subtract:
93         scherzo->staff_height -= 4;
94         gtk_widget_queue_draw (widget);
95         return TRUE;
96         break;
97     case GDK_KEY_q:
98     case GDK_KEY_Q:
99     case GDK_KEY_Escape:
100         gtk_main_quit ();
101         return FALSE;
102     }
103
104     /* Allow the event to propagate to other handlers. */
105     return FALSE;
106 }
107
108 int
109 main (int argc, char *argv[])
110 {
111     GtkWidget *window;
112     GtkWidget *drawing_area;
113     scherzo_t scherzo;
114     score_staff_t *treble;
115     score_staff_t *bass;
116
117     gtk_init (&argc, &argv);
118
119     scherzo.score = score_create (NULL);
120     scherzo.staff_height = 48;
121     score_set_staff_height (scherzo.score, scherzo.staff_height);
122
123     score_add_brace (scherzo.score, 2);
124     treble = score_add_staff (scherzo.score, SCORE_CLEF_G);
125     bass = score_add_staff (scherzo.score, SCORE_CLEF_F);
126
127     score_staff_add_note (treble, SCORE_BUILD_NOTE (D, 4, WHOLE));
128     score_staff_add_note (treble, SCORE_BUILD_NOTE (E, 4, WHOLE));
129     score_staff_add_note (treble, SCORE_BUILD_NOTE (F, 4, WHOLE));
130     score_staff_add_note (treble, SCORE_BUILD_NOTE (G, 4, WHOLE));
131     score_staff_add_note (treble, SCORE_BUILD_NOTE (A, 4, WHOLE));
132     score_staff_add_note (treble, SCORE_BUILD_NOTE (B, 4, WHOLE));
133     score_staff_add_note (treble, SCORE_BUILD_NOTE (C, 5, WHOLE));
134     score_staff_add_note (treble, SCORE_BUILD_NOTE (D, 5, WHOLE));
135
136     score_staff_add_note (bass, SCORE_BUILD_NOTE (B, 2, WHOLE));
137     score_staff_add_note (bass, SCORE_BUILD_NOTE (C, 3, WHOLE));
138     score_staff_add_note (bass, SCORE_BUILD_NOTE (D, 3, WHOLE));
139     score_staff_add_note (bass, SCORE_BUILD_NOTE (E, 3, WHOLE));
140     score_staff_add_note (bass, SCORE_BUILD_NOTE (F, 3, WHOLE));
141     score_staff_add_note (bass, SCORE_BUILD_NOTE (G, 3, WHOLE));
142     score_staff_add_note (bass, SCORE_BUILD_NOTE (A, 3, WHOLE));
143     score_staff_add_note (bass, SCORE_BUILD_NOTE (B, 3, WHOLE));
144
145     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
146
147     gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
148
149     g_signal_connect (window, "delete-event",
150                       G_CALLBACK (on_delete_event_quit), NULL);
151
152     drawing_area = gtk_drawing_area_new ();
153
154     gtk_container_add (GTK_CONTAINER (window), drawing_area);
155
156     g_signal_connect (drawing_area, "expose-event",  
157                       G_CALLBACK (on_expose_event_draw),
158                       &scherzo);
159
160     g_signal_connect (window, "key-press-event",  
161                       G_CALLBACK (on_key_press_event),
162                       &scherzo);
163     
164     gtk_widget_show_all (window);
165     
166     gtk_main ();
167
168     return 0;
169 }