Listing 4: The implementation of the numeric keypad widget requires less than 150 lines of code
#include "gtk/gtktable.h" #include "gtk/gtkbutton.h" #include "gtk/gtklabel.h" #include "numberpad.h" void numberpad_clicked(GtkWidget* widget, Numberpad* numberpad) { if (widget == numberpad->enterButton) { if (strlen(numberpad->numbers) > 0) { int value = atoi(numberpad->numbers); if (value >= numberpad->adjustment->lower && value <= numberpad->adjustment->upper) { numberpad->adjustment->value = value; gtk_signal_emit_by_name( GTK_OBJECT(numberpad->adjustment), "value_changed"); } numberpad->numbers[0] = 0; } } else { int numbersLength = strlen(numberpad->numbers); gchar* label; gtk_label_get(GTK_LABEL(GTK_BIN(widget)->child), &label); if (numbersLength < 3) { numberpad->numbers[numbersLength] = label[0]; numberpad->numbers[numbersLength+1] = 0; } } } void numberpad_init(Numberpad* numberpad) { GtkWidget* table; gint row, column, number, index; table = gtk_table_new(3, 4, FALSE); gtk_container_add(GTK_CONTAINER(numberpad), table); gtk_widget_show(table); // Add the buttons 1 through 9... number = 1; for (row = 2; row >= 0; row--) for (column = 0; column < 3; column++) { unsigned char buffer[2]; sprintf(buffer, "%i", number++); index = row * 3 + column; numberpad->numberButtons[index] = gtk_button_new_with_label(buffer); gtk_table_attach_defaults( GTK_TABLE(table), numberpad->numberButtons[index], column, column+1, row, row+1); gtk_signal_connect( GTK_OBJECT(numberpad->numberButtons[index]), "clicked", GTK_SIGNAL_FUNC(numberpad_clicked), numberpad); gtk_widget_show(numberpad->numberButtons[index]); } // Special case for adding the 0 button... index = 9; numberpad->numberButtons[index] = gtk_button_new_with_label("0"); gtk_table_attach_defaults( GTK_TABLE(table), numberpad->numberButtons[index], 0, 1, 3, 4); gtk_signal_connect( GTK_OBJECT(numberpad->numberButtons[index]), "clicked", GTK_SIGNAL_FUNC(numberpad_clicked), numberpad); gtk_widget_show(numberpad->numberButtons[index]); // And finally, add the Enterbutton... numberpad->enterButton = gtk_button_new_with_label("Enter"); gtk_table_attach_defaults( GTK_TABLE(table), numberpad->enterButton, 1, 3, 3, 4); gtk_signal_connect( GTK_OBJECT(numberpad->enterButton), "clicked", GTK_SIGNAL_FUNC(numberpad_clicked), numberpad); gtk_widget_show(numberpad->enterButton); } guint numberpad_get_type() { static guint numberpad_type = 0; if (!numberpad_type) { GtkTypeInfo numberpad_info = { "Numberpad", sizeof(Numberpad), sizeof(GtkVBoxClass), NULL, (GtkObjectInitFunc) numberpad_init, NULL, NULL, NULL }; numberpad_type = gtk_type_unique( gtk_vbox_get_type(), &numberpad_info); } return numberpad_type; } GtkWidget* numberpad_new(GtkAdjustment* adjustment) { Numberpad *numberpad; numberpad = gtk_type_new(numberpad_get_type()); numberpad->adjustment = adjustment; numberpad->numbers[0] = 0; return GTK_WIDGET(numberpad); }s