Created
March 11, 2013 13:19
-
-
Save pce/5134167 to your computer and use it in GitHub Desktop.
gcc -Wall drawarea.c -o drawarea `pkg-config --cflags --libs gtk+-2.0`
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <gtk/gtk.h> | |
| #include <gdk/gdkkeysyms.h> | |
| static gboolean button_pressed (GtkWidget*, GdkEventButton*, GArray*); | |
| static gboolean motion_notify (GtkWidget*, GdkEventMotion*, GPtrArray*); | |
| static gboolean key_pressed (GtkWidget*, GdkEventKey*, GPtrArray*); | |
| static gboolean expose_event (GtkWidget*, GdkEventExpose*, GArray*); | |
| static gboolean ui_draw_grid (GtkWidget *area); | |
| static gboolean ui_draw_boxes (GtkWidget *area); | |
| static gboolean ui_redraw (GtkWidget *area, GArray *steparray); | |
| int main (int argc, | |
| char *argv[]) | |
| { | |
| GtkWidget *window, *area; | |
| GPtrArray *parray; | |
| GArray *steparray; | |
| GArray *garray; | |
| gint i; | |
| gtk_init (&argc, &argv); | |
| gtk_rc_parse(".gtkrc"); | |
| window = gtk_window_new (GTK_WINDOW_TOPLEVEL); | |
| gtk_window_set_title (GTK_WINDOW (window), "iobb"); | |
| gtk_widget_set_size_request (window, 400, 300); | |
| g_signal_connect (G_OBJECT (window), "destroy", | |
| G_CALLBACK (gtk_main_quit), NULL); | |
| /* Create a pointer array to hold image data. Then, add event masks to the new | |
| * drawing area widget. */ | |
| parray = g_ptr_array_sized_new (5000); | |
| steparray = g_array_new (FALSE, FALSE, sizeof (guint)); | |
| area = gtk_drawing_area_new (); | |
| GTK_WIDGET_SET_FLAGS (area, GTK_CAN_FOCUS); | |
| gtk_widget_add_events (area, GDK_BUTTON_PRESS_MASK | | |
| GDK_BUTTON_MOTION_MASK | | |
| GDK_KEY_PRESS_MASK); | |
| g_signal_connect (G_OBJECT (area), "button_press_event", | |
| G_CALLBACK (button_pressed), steparray); | |
| g_signal_connect (G_OBJECT (area), "motion_notify_event", | |
| G_CALLBACK (motion_notify), parray); | |
| g_signal_connect (G_OBJECT (area), "key_press_event", | |
| G_CALLBACK (key_pressed), parray); | |
| g_signal_connect (G_OBJECT (area), "expose_event", | |
| G_CALLBACK (expose_event), steparray); | |
| gtk_container_add (GTK_CONTAINER (window), area); | |
| gtk_widget_show_all (window); | |
| /* You must do this after the widget is visible because it must first | |
| * be realized for the GdkWindow to be valid! */ | |
| gdk_window_set_cursor (area->window, gdk_cursor_new (GDK_PENCIL)); | |
| gtk_main (); | |
| g_array_free (steparray, TRUE); | |
| return 0; | |
| } | |
| /* Redraw all of the points when an expose-event occurs. If you do not do this, | |
| * the drawing area will be cleared. */ | |
| static gboolean | |
| expose_event (GtkWidget *area, | |
| GdkEventExpose *event, | |
| GArray *steparray) | |
| { | |
| guint i, j, x, y, w, h; | |
| /* | |
| w = SEQ_WIDTH/SEQ_STEPS; | |
| h = SEQ_HEIGHT/SEQ_TRACKS; | |
| */ | |
| w = 9; | |
| h = 9; | |
| /* Loop through steps. */ | |
| for (i = 0; i < steparray->len; i = i + 2) { | |
| /* x = GPOINTER_TO_INT (steparray->data[i]); | |
| y = GPOINTER_TO_INT (steparray->data[i+1]); */ | |
| x = g_array_index (steparray, guint, i); | |
| y = g_array_index (steparray, guint, i+1); | |
| for (i = 10; i < 400; i+=10) { | |
| for (j = 10; j < 300; j+=10) { | |
| if (i == x && j == y) { | |
| gdk_draw_rectangle(area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| TRUE, | |
| i+1,j+1,w,h); | |
| } | |
| } | |
| } | |
| } | |
| ui_draw_grid (area); | |
| return TRUE; | |
| } | |
| /* Redraw all of the points when an expose-event occurs. If you do not do this, | |
| * the drawing area will be cleared. */ | |
| static gboolean | |
| ui_redraw (GtkWidget *area, | |
| GArray *steparray) | |
| { | |
| guint step, i, j, x, y, w, h; | |
| w = 9; | |
| h = 9; | |
| /* iobb Loop through steps. */ | |
| for (step = 0; step < steparray->len; step = step + 2) { | |
| /* x = steparray->data[i]; | |
| y = steparray->data[i+1]; */ | |
| x = g_array_index (steparray, guint, step); | |
| y = g_array_index (steparray, guint, step+1); | |
| g_print ("[redraw][%d] x:%d, y:%d\n", step, x, y); | |
| for (i = 10; i < 400; i+=10) { | |
| for (j = 10; j < 300; j+=10) { | |
| if (i == x && j == y) { | |
| gdk_draw_rectangle(area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| TRUE, | |
| i+1,j+1,w,h); | |
| } | |
| } | |
| } | |
| } | |
| ui_draw_grid (area); | |
| return TRUE; | |
| } | |
| static gboolean | |
| ui_draw_boxes (GtkWidget *area) | |
| { | |
| guint i, j, w, h; | |
| w = 5; | |
| h = 5; | |
| for (i = 0; i < 400; i+=10) | |
| for (j = 0; j < 300; j+=10) | |
| gdk_draw_rectangle(area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| TRUE, | |
| i,j,w,h); | |
| return TRUE; | |
| } | |
| static gboolean | |
| ui_draw_grid (GtkWidget *area) | |
| { | |
| guint i, j, x, y, w, h; | |
| w = 9; | |
| h = 9; | |
| for (i = 10; i < 400; i+=10) { | |
| for (j = 10; j < 300; j+=10) { | |
| if (i == 20 && j == 40) { | |
| gdk_draw_rectangle(area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| TRUE, | |
| i+1,j+1,w,h); | |
| } | |
| gdk_draw_point(area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| i,j); | |
| } | |
| } | |
| return TRUE; | |
| } | |
| /* Draw a point where the user pressed the mouse and points on each of the | |
| * four sides of that point. */ | |
| static gboolean | |
| button_pressed (GtkWidget *area, | |
| GdkEventButton *event, | |
| GArray *steparray) | |
| { | |
| guint x = event->x, y = event->y, track, step, i, j; | |
| gboolean track_set, step_set; | |
| track_set = FALSE; | |
| step_set = FALSE; | |
| g_print("[button_pressed] x:%d, y:%d\n", x, y); | |
| for (i = 10; i < 400; i+=10) { | |
| for (j = 10; j < 300; j+=10) { | |
| if (i > x && !track_set) { | |
| track = i -10; | |
| track_set = TRUE; | |
| } | |
| if (j > y && !step_set) { | |
| step = j -10; | |
| step_set = TRUE; | |
| } | |
| } | |
| } | |
| g_array_append_val (steparray, track); | |
| g_array_append_val (steparray, step); | |
| g_print("[button_pressed] steps:%d\n", steparray->len); | |
| g_print("[button_pressed] track:%d, step:%d\n", track, step); | |
| ui_redraw (area, steparray); | |
| return FALSE; | |
| } | |
| /* Draw a point where the moved the mouse pointer while a button was | |
| * pressed along with points on each of the four sides of that point. */ | |
| static gboolean | |
| motion_notify (GtkWidget *area, | |
| GdkEventMotion *event, | |
| GPtrArray *parray) | |
| { | |
| guint x = event->x, y = event->y; | |
| GdkPoint points[5] = { {x,y}, {x+1,y}, {x-1,y}, {x,y+1}, {x,y-1} }; | |
| gdk_draw_points (area->window, | |
| area->style->fg_gc[GTK_WIDGET_STATE (area)], | |
| points, 5); | |
| g_ptr_array_add (parray, GINT_TO_POINTER (x)); | |
| g_ptr_array_add (parray, GINT_TO_POINTER (y)); | |
| return FALSE; | |
| } | |
| /* Clear the drawing area when the user presses the Delete key. */ | |
| static gboolean | |
| key_pressed (GtkWidget *area, | |
| GdkEventKey *event, | |
| GPtrArray *parray) | |
| { | |
| if (event->keyval == GDK_Delete) | |
| { | |
| gdk_window_clear (area->window); | |
| g_ptr_array_remove_range (parray, 0, parray->len); | |
| } | |
| return FALSE; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment