Help with expose/configure events - please



OK, I've looked at the tutorial and tried to follow it. I've even stared
at my code for long hours and can't seem to find anything wrong with it.
;) So could somebody who's a little bit more familiar with GTK+ and X
try compiling this and tell me what I need to change? Currently, the
drawing areas will come up gray (I want them black) and the drawing
areas are not redrawn when the window is exposed.

Thanks!
Nathan

/* defines for the array of buttons and drawing areas */
/* theoretically, the array can be made as large as you desire */
/* be aware that you might have to change the arguments */
/* to gtk_widget_set_usize() in main() if you change these */
#define WIDTH 3
#define HEIGHT 3

/* your standard includes */
#include <stdlib.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>

/* make the adjustments global to avoid some function calls */
/* heck, make everything global! */
GtkObject *sdata[3];
GtkWidget *scroll[3];

/* labels for the scrollbars */
GtkWidget *label[3];
char *names[3] = { "Red", "Green", "Blue" };

GtkWidget *window;
GtkWidget *drawbox[(WIDTH)*(HEIGHT)]; /* where to draw the selected
color */
GdkPixmap *pixmap[(WIDTH)*(HEIGHT)]; /* store the drawing in memory */
GtkWidget *checkbox[(WIDTH)*(HEIGHT)]; /* must be the same as above! */
GtkWidget *entry[3];
GdkColor *color;
GdkGC *gc;
int width, height;
int which; /* decide which box to color */
int old[(WIDTH)*(HEIGHT)][3]; /* holding array for old RGB values */

char buffer[16];

void set_colors();
void set_sliders();
void set_entry_text(int);
void configure_gc(int);

void
destroy(GtkWidget *widget, gpointer *data)
{
    gtk_main_quit();
}

void
update_sliders(GtkObject *widget, gpointer *data)
{
    int k;

    for(k=0;k<3;k++){
	if(GTK_ADJUSTMENT(sdata[k]) == GTK_ADJUSTMENT(widget))
	    set_entry_text(k);
    }
  
    set_colors();
}

/* make SURE the entry text corresponds to slider values! */
void
set_entry_text(int index)
{
    sprintf(buffer, "%d", (int)GTK_ADJUSTMENT(sdata[index])->value);
    
    gtk_signal_handler_block_by_data(GTK_OBJECT(entry[index]), NULL);
    gtk_entry_set_text(GTK_ENTRY(entry[index]), buffer);
    gtk_signal_handler_unblock_by_data(GTK_OBJECT(entry[index]), NULL);
}

/* figure out which button and drawing area we're working with */
void
update_boxes(GtkWidget *widget, gpointer *data)
{
    int k;

    if(!GTK_TOGGLE_BUTTON(widget)->active)
	return;
    if(GTK_TOGGLE_BUTTON(widget) == GTK_TOGGLE_BUTTON(checkbox[which]))
	return;
    for(k=0;k<((WIDTH)*(HEIGHT));k++) {
	if(GTK_TOGGLE_BUTTON(checkbox[k])==GTK_TOGGLE_BUTTON(widget))
	    which = k;
	else
	    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(checkbox[k]), FALSE);
    }

    for(k=0;k<3;k++) {
	/* make sure our code doesn't go strange places... */
	gtk_signal_handler_block_by_data(GTK_OBJECT(sdata[k]), NULL);
	gtk_adjustment_set_value(GTK_ADJUSTMENT(sdata[k]), old[which][k]);
	gtk_signal_handler_unblock_by_data(GTK_OBJECT(sdata[k]), NULL);
	
	gtk_range_slider_update(GTK_RANGE(scroll[k]));
	
	set_entry_text(k);
    }

    set_colors(1);
}

/* the callback for the entry widgets */
void
update_labels(GtkWidget *widget, gpointer *data)
{
    int k, num;

    for(k=0;k<3;k++) {
	if(GTK_ENTRY(entry[k])==GTK_ENTRY(widget)){
	    num = atoi(gtk_entry_get_text(GTK_ENTRY(widget)));
	    if(num>255) /* kludge */
		num = 255;
	    if(num == GTK_ADJUSTMENT(sdata[k])->value)
		return;
	    gtk_signal_handler_block_by_data(GTK_OBJECT(sdata[k]), NULL);
	    gtk_adjustment_set_value(GTK_ADJUSTMENT(sdata[k]), (gfloat)num);
	    gtk_signal_handler_unblock_by_data(GTK_OBJECT(sdata[k]), NULL);
	}
    }
  
    set_sliders();
    set_colors(1);
}

/* this function set the sliders as determined by the labels */
void
set_sliders()
{
    int k;

    for(k=0;k<3;k++) {
	GTK_ADJUSTMENT(sdata[k])->value =
atoi(gtk_entry_get_text(GTK_ENTRY(entry[k])));
	gtk_range_slider_update(GTK_RANGE(scroll[k]));
    }
}

/* this function actually sets the colors of the drawbox determined by
which */
/* 'update' indicates whether to draw the slider values or the old
values */
void
set_colors(int update)
{
    int k;

    if(update) {
	for(k=0;k<3;k++) {
	    old[which][k] =  (int)GTK_ADJUSTMENT(sdata[k])->value;
	}
    }

    gdk_window_get_size(drawbox[which]->window, &width, &height);

    /* setup the color for the foreground */
    configure_gc(which);

    gdk_draw_rectangle(drawbox[which]->window, gc, TRUE, 0, 0, width,
height);
}

gint
handle_configure(GtkWidget *widget, gpointer *data)
{
    int k, save;

    for(k=0;k<(WIDTH*HEIGHT);k++) {
	if(GTK_DRAWING_AREA(widget) == GTK_DRAWING_AREA(drawbox[k])) {
	    if(pixmap[k])
		gdk_pixmap_unref(pixmap[k]);
	    pixmap[which] = gdk_pixmap_new(widget->window,
					   widget->allocation.width,
					   widget->allocation.height,
					   -1);
	    configure_gc(k);
	    
	    gdk_draw_rectangle(pixmap[k],
			       gc,
			       TRUE,
			       0, 0,
			       widget->allocation.width,
			       widget->allocation.height);
	}
    }
    
    return TRUE;
}

void
configure_gc(int index)
{
    if(!gc)
	gc = gdk_gc_new(drawbox[index]->window);

    color->red = old[index][0] * (65535/255);
    color->green = old[index][1] * (65535/255);
    color->blue = old[index][2] * (65535/255);
    color->pixel = (gulong)(old[index][0]*65536 + old[index][1]*256 +
old[index][2]);

    gdk_color_alloc(gtk_widget_get_colormap(drawbox[index]), color);

    gdk_gc_set_foreground(gc, color);
}
  
gint
handle_expose(GtkWidget *widget, GdkEventExpose *event)
{
    int k;
    
    for(k=0;k<(WIDTH*HEIGHT);k++) {
	if(GTK_DRAWING_AREA(widget) == GTK_DRAWING_AREA(drawbox[k])) {
	    gdk_draw_pixmap(widget->window,
			    gc,
			    pixmap[k],
			    event->area.x, event->area.y,
			    event->area.x, event->area.y,
			    event->area.width, event->area.height);
	}
    }

    return FALSE;
}

int
main(int argc, char *argv[])
{
    GtkWidget *scrollbox;
    GtkWidget *table; /* ! */
    GtkWidget *column[HEIGHT];
    GtkWidget *row[(WIDTH)*(HEIGHT)];
    GSList *group;
    int i, j, k;
  
    void destroy(GtkWidget *, gpointer *);
    void update_sliders(GtkObject *, gpointer *);
    void update_labels(GtkWidget *, gpointer *);
    gint handle_configure(GtkWidget *, gpointer *);
    gint handle_expose(GtkWidget *, GdkEventExpose *);

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_signal_connect(GTK_OBJECT(window), "delete_event",
GTK_SIGNAL_FUNC(destroy), NULL);
    gtk_container_border_width(GTK_CONTAINER(window), 10);
    gtk_widget_set_usize(window, 400, 400);

    color = (GdkColor *)malloc(sizeof(GdkColor));
    color->red = 0;
    color->green = 0;
    color->blue = 0;
    color->pixel = 0;
  
    scrollbox = gtk_vbox_new(TRUE, 3);

    table = gtk_table_new (3, 3, FALSE);
    gtk_table_set_row_spacings(GTK_TABLE(table), 3);
    gtk_table_set_col_spacings(GTK_TABLE(table), 3);
    gtk_box_pack_start(GTK_BOX(scrollbox), table, TRUE, TRUE, 0);

    for(i=0;i<3;i++) {
	label[i] = gtk_label_new(names[i]);
	sdata[i] = gtk_adjustment_new(0.0, 0.0, 256.0, 1.0, 8.0, 1.0);
	scroll[i] = gtk_hscrollbar_new(GTK_ADJUSTMENT(sdata[i]));
	entry[i] = gtk_entry_new();

	gtk_widget_set_usize(GTK_WIDGET(entry[i]), 40, 0);
	gtk_entry_set_text(GTK_ENTRY(entry[i]), "0");
	
	gtk_table_attach(GTK_TABLE(table), label[i],
			 0, 1, i, i+1, GTK_FILL, GTK_EXPAND, 0, 0);
	gtk_table_attach(GTK_TABLE(table), scroll[i],
			 1, 2, i, i+1, GTK_EXPAND | GTK_FILL, GTK_EXPAND, 0, 0);
	gtk_table_attach(GTK_TABLE(table), entry[i],
			 2, 3, i, i+1, GTK_FILL, GTK_EXPAND, 0, 0);
	
	gtk_signal_connect(GTK_OBJECT(sdata[i]), "value_changed",
			   GTK_SIGNAL_FUNC(update_sliders), NULL);
	gtk_signal_connect(GTK_OBJECT(entry[i]), "changed",
			   GTK_SIGNAL_FUNC(update_labels), NULL);
	
	/* show what we just made */
	gtk_widget_show(label[i]);
	gtk_widget_show(scroll[i]);
	gtk_widget_show(entry[i]);
    }

    gtk_widget_show(table);

    group = NULL; /* get everything started on the right foot */

    for(i=0;i<HEIGHT;i++){
	column[i] = gtk_hbox_new(TRUE, 0);
	for(j=0;j<WIDTH;j++){
      
	    /* create everything */
	    drawbox[WIDTH*i+j] = gtk_drawing_area_new();
	    checkbox[WIDTH*i+j] = gtk_radio_button_new(group);
	    group =
gtk_radio_button_group(GTK_RADIO_BUTTON(checkbox[WIDTH*i+j]));
	    row[WIDTH*i+j] = gtk_hbox_new(FALSE, 0);
      
	    /* initialize the "old" values array */
	    for(k=0;k<3;k++)
		old[WIDTH*i+j][k] = 0;
      
	    /* pack everything into boxes */
	    gtk_box_pack_start(GTK_BOX(row[WIDTH*i+j]),checkbox[WIDTH*i+j],
FALSE, FALSE, 0);
	    gtk_box_pack_start(GTK_BOX(row[WIDTH*i+j]),drawbox[WIDTH*i+j],
TRUE, TRUE, 0);
	    gtk_box_pack_start(GTK_BOX(column[i]), row[WIDTH*i+j], FALSE, TRUE,
0);
      
	    /* show everything we just created! */
	    gtk_widget_show(checkbox[WIDTH*i+j]);
	    gtk_widget_show(drawbox[WIDTH*i+j]);
	    gtk_widget_show(row[WIDTH*i+j]);

	    /* connect signals */
	    gtk_signal_connect(GTK_OBJECT(checkbox[WIDTH*i+j]), "toggled",
			       GTK_SIGNAL_FUNC(update_boxes), NULL);
	    gtk_signal_connect_after(GTK_OBJECT(drawbox[WIDTH*i+j]),
"expose_event",
	    		       GTK_SIGNAL_FUNC(handle_expose), NULL);
	    gtk_signal_connect_after(GTK_OBJECT(drawbox[WIDTH*i+j]),
"configure_event",
			       GTK_SIGNAL_FUNC(handle_configure), NULL);
	}
	gtk_box_pack_start(GTK_BOX(scrollbox), column[i], TRUE, TRUE, 0);
	gtk_widget_show(column[i]);
    }
  
    which =0;
    gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(checkbox[which]),
TRUE);

    gtk_container_add(GTK_CONTAINER(window), scrollbox);
    gtk_widget_show(scrollbox);
  
    gtk_widget_show(window);
    gtk_main();

    free((void *)color);
  
    return 0;
}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]