The Basic Widget TourAs a Program

only for RuBoard - do not distribute or recompile

The program in Listing 2.2 is a short demonstration of what is required to build a GTK+ application. Listing 2.2 is a tour of the basic widgets: label, command button, toggle, check and radio buttons, List, and CList. The running program is designed to demonstrate the functionality of these widgets. It does nothing special, but it attempts to tie together some of the more common widgets to show how they work.

Listing 2.2 Working Tour of Some Basic GTK+ Widgets
 #include <gtk/gtk.h>  /* These are the top-level windows. Normally, they would   * be the only global variables, but in order to demonstrate   * widget functionality, many widgets are declared global   * that normally wouldn't be in a production   * application. */  GtkWidget *frm_main;  GtkWidget *frm_buttons;  GtkWidget *frm_text_entry;    GtkWidget *frm_list_widgets;  /* ================ Main Window ======================= */  void destroy_main(GtkWidget *frm_main, gpointer data);  void show_frm_buttons();  void show_frm_text_entry();  void show_frm_list_widgets();  void MsgBox(gpointer gdata);  gint main(gint argc, gchar * argv[])  {    GtkWidget *vbox;     GtkWidget *cmd_buttons;     GtkWidget *cmd_text_entry;     GtkWidget *cmd_list_widgets;     gtk_init(&argc, &argv);     frm_main = gtk_window_new(GTK_WINDOW_TOPLEVEL);  /* The following line is where you could set the default window   * size, in pixels. Without this, it will default to the smallest   * size that can still completely hold all widgets. */   /* gtk_window_set_default_size(GTK_WINDOW(frm_main), 200, 300); */  gtk_window_set_title(GTK_WINDOW(frm_main), "Widgets Demo");  /* Instantiate a vertical packing box with three button widgetsthe   * main control box of the program.   */  vbox = gtk_vbox_new(TRUE, 0);     cmd_buttons = gtk_button_new_with_label("Buttons Demo");     cmd_text_entry = gtk_button_new_with_label("Text and Entry Demo");     cmd_list_widgets = gtk_button_new_with_label("List and CList Demo");     gtk_signal_connect(GTK_OBJECT(cmd_buttons),           "clicked",           GTK_SIGNAL_FUNC(show_frm_buttons),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_text_entry),           "clicked",           GTK_SIGNAL_FUNC(show_frm_text_entry),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_list_widgets),           "clicked",           GTK_SIGNAL_FUNC(show_frm_list_widgets),           NULL);     gtk_signal_connect(GTK_OBJECT(frm_main),           "destroy",           GTK_SIGNAL_FUNC (destroy_main),           NULL);  /* Now, pack the buttons into the vertical packing box **/  gtk_box_pack_start(GTK_BOX(vbox), cmd_buttons, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox), cmd_text_entry, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox), cmd_list_widgets, TRUE, TRUE, 0);     gtk_container_add(GTK_CONTAINER(frm_main), vbox);  /* Finally, make the main window visible, and transfer control   * to gtk_main();   */  gtk_widget_show_all (frm_main);     gtk_main ();     return 0;  }  void destroy_main(GtkWidget * frm_main, gpointer data)  {  /* This function removes the necessity of hitting Ctrl+C to finally   * terminate your program after the last window has been closed.   */  gtk_main_quit();  }  /* =================== Utility Functions =================== */  void MsgBox(gpointer gdata)  {  /* In this utility function, gdata is the message you want to show your   * message box.   */  GtkWidget *msg_box_window;     GtkWidget *vbox;     GtkWidget *top_label;  /* You could put an OK button in here if you wanted   * to, but since this is a demo, I will just use the   * Close window button in the upper-right of the window. */  msg_box_window = gtk_window_new(GTK_WINDOW_DIALOG);     gtk_window_set_default_size(GTK_WINDOW(msg_box_window), 150, 100);     gtk_window_set_title(GTK_WINDOW(msg_box_window), "Message Box");     gtk_window_set_modal(GTK_WINDOW(msg_box_window), TRUE);     g_print("msgbox window created...\n");  /* Actually, for this simple implementation, a packing box   * is not technically necessary. However, having it will   * make it easier to add other widgets later (such as   * an "OK" button).   */  vbox = gtk_vbox_new(TRUE, 0);  /* The following line creates a label with a dummy message, and   * then it fills in the correct message to display. It is done   * this way to demonstrate the functions, not necessarily because   * it has to be done this way.   */  top_label = gtk_label_new("this is the label");     gtk_label_set_text(GTK_LABEL(top_label), gdata);     g_print("child widgets created...\n");     gtk_box_pack_start(GTK_BOX(vbox), top_label, TRUE, TRUE, 0);     gtk_container_add(GTK_CONTAINER(msg_box_window), vbox);     gtk_widget_show_all (msg_box_window);  }  /* ================= Buttons Demo Window ================== */   /* The following widgets are made global for ease of   * demonstration, not good software engineering.   * See the "lookup widget" function in support.c of the   * Glade section for the proper way to handle this. */  GtkWidget *lbl_second;  GtkWidget *toggle_third;  GtkWidget *chk_button;  /* These are the command button events. */  void cmd_top_clicked();  void cmd_top_pressed();  void cmd_top_released();  void cmd_top_enter();  void cmd_top_leave();  /* These are the toggle button functions. */  void toggle_third_toggled();  void toggle_third_clicked();  void cmd_toggle_state_clicked();  void cmd_toggle_up_or_down_clicked();  void cmd_toggle_up_clicked();  void cmd_toggle_down_clicked();  /* These are the check button functions. */  void cmd_chk_button_state_clicked();  void show_frm_buttons() {  /* This function creates and displays the window, with the title   * "Buttons Demo Form," which is shown in   Figure 2.2   .   */  GtkWidget *button_vbox;     GtkWidget *cmd_top;     GtkWidget *cmd_toggle_state;     GtkWidget *cmd_toggle_up_or_down;     GtkWidget *cmd_toggle_up, *cmd_toggle_down;     GtkWidget *cmd_chk_button_state;     GtkWidget *rdo_grp1_btnA, *rdo_grp1_btnB, *rdo_grp1_btnC;     GtkWidget *rdo_grp2_btnA, *rdo_grp2_btnB, *rdo_grp2_btnC;  /* The following is for the group-1 radio buttons. */  GSList *grp1 = NULL;  /* Notice that the form isn't actually built until the   * user clicks on the command button. */  frm_buttons = gtk_window_new(GTK_WINDOW_TOPLEVEL);     gtk_window_set_title(GTK_WINDOW(frm_buttons), "Buttons Demo Form");     button_vbox = gtk_vbox_new(TRUE, 0);     cmd_top = gtk_button_new_with_label("This button just shows events");  /* Connect the signals to functions.   * These are the five signals for a command button. */  gtk_signal_connect(GTK_OBJECT(cmd_top),           "clicked",           GTK_SIGNAL_FUNC(cmd_top_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_top),           "pressed",           GTK_SIGNAL_FUNC(cmd_top_pressed),           NULL);  /* Be advised: When a command button is pressed, the clicked   * event occurs before the release event. */  gtk_signal_connect(GTK_OBJECT (cmd_top),           "released",           GTK_SIGNAL_FUNC(cmd_top_released),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_top),           "enter",           GTK_SIGNAL_FUNC(cmd_top_enter),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_top),           "leave",             GTK_SIGNAL_FUNC(cmd_top_leave),           NULL);  /* The event sequence for the command button is: entered,   * pressed, clicked, released, leave. */  lbl_second = gtk_label_new("This is a label. The label has no events.");     toggle_third = gtk_toggle_button_new_with_label("This is a toggle button.");  /* Because the toggle button is derived from the standard   * command button, it has all the same events, plus the   * "toggled" event, below. However, only the clicked event is   * demonstrated. */  gtk_signal_connect(GTK_OBJECT(toggle_third),           "toggled",           GTK_SIGNAL_FUNC(toggle_third_toggled),           NULL);     gtk_signal_connect(GTK_OBJECT(toggle_third),           "clicked",           GTK_SIGNAL_FUNC(toggle_third_clicked),           NULL);  /* Be advised: The toggle event occurs before the clicked event.   * Therefore, the event sequence is: entered, pressed, toggled, clicked,   * released, and leave. */   /* The following command button checks the state   * of the toggle button when clicked. */  cmd_toggle_state = gtk_button_new_with_label        ("What is the state of the above toggle?");     gtk_signal_connect(GTK_OBJECT(cmd_toggle_state),           "clicked",           GTK_SIGNAL_FUNC(cmd_toggle_state_clicked),           NULL);  /* This next command button is used to switch the   * toggle button to the other state from   * whatever state it is currently in. */  cmd_toggle_up_or_down = gtk_button_new_with_label("Toggle to other position.");     gtk_signal_connect(GTK_OBJECT(cmd_toggle_up_or_down),           "clicked",           GTK_SIGNAL_FUNC(cmd_toggle_up_or_down_clicked),           NULL);  /* These next two command buttons explicitly   * place the toggle button in the up or down position. */  cmd_toggle_up = gtk_button_new_with_label("Toggle UP!");     cmd_toggle_down = gtk_button_new_with_label("Toggle DOWN!");     gtk_signal_connect(GTK_OBJECT(cmd_toggle_up),           "clicked",           GTK_SIGNAL_FUNC(cmd_toggle_up_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_toggle_down),           "clicked",           GTK_SIGNAL_FUNC(cmd_toggle_down_clicked),           NULL);  /* Moving on to the check button widget   * First, I will create it,   * then I will demonstrate some of the functions for it.*/  chk_button = gtk_check_button_new_with_label("This is the Czech Button.");     cmd_chk_button_state = gtk_button_new_with_label                            ("What is the state of the Czech Button?");     gtk_signal_connect(GTK_OBJECT(cmd_chk_button_state),           "clicked",           GTK_SIGNAL_FUNC(cmd_chk_button_state_clicked),           NULL);  /* Finally, I will finish up with the radio buttons   * widget. There will be two different groups of radio   * buttons: one in which the group is created manually and   * one in which the group is created automatically. First, the   * hard (manual) way... Remember,, the GtkFrame object does   * not automatically group radio buttons for you.   *   * For each of the three following radio buttons, the first line   * creates the radio button, and the second line adds it to grp1.   * Remember, grp1 is of type GSList. */  rdo_grp1_btnA = gtk_radio_button_new_with_label(grp1, "Group 1, Choice A");     grp1 = gtk_radio_button_group(GTK_RADIO_BUTTON(rdo_grp1_btnA));     rdo_grp1_btnB = gtk_radio_button_new_with_label(grp1, "Group 1, Choice B");     grp1 = gtk_radio_button_group(GTK_RADIO_BUTTON(rdo_grp1_btnB));     rdo_grp1_btnC = gtk_radio_button_new_with_label(grp1, "Group 1, Choice C");     grp1 = gtk_radio_button_group(GTK_RADIO_BUTTON(rdo_grp1_btnC));  /* The above radio buttons will be added to the bottom of the packing   * box later.   *   * Now, to add a radio button group the easy way */  rdo_grp2_btnA = gtk_radio_button_new_with_label(NULL, "Group 2, Choice A");  /* When you create a new radio button with the "group" parameter   * set to NULL, GTK+ creates a default group for you. Then, to   * add other radio buttons to the same group as another radio   * button, you get the group of the first radio button and send   * it as the parameter when you create the additional radio   * buttons for the group, as shown below */  rdo_grp2_btnB = gtk_radio_button_new_with_label        (gtk_radio_button_group(GTK_RADIO_BUTTON(rdo_grp2_btnA)),         "Group 2, Choice B");     rdo_grp2_btnC = gtk_radio_button_new_with_label        (gtk_radio_button_group(GTK_RADIO_BUTTON(rdo_grp2_btnA)),         "Group 2, Choice C");  /* Notice that the following lines pack the vbox from the top down.   * Also, notice that I did not have to declare the number of spaces   * for child widgets in the vbox; they are added dynamically. */  gtk_box_pack_start(GTK_BOX(button_vbox), cmd_top, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), lbl_second, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), toggle_third, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), cmd_toggle_state, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), cmd_toggle_up_or_down,TRUE,TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), cmd_toggle_up, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), cmd_toggle_down, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), chk_button, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), cmd_chk_button_state,TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp1_btnA, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp1_btnB, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp1_btnC, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp2_btnA, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp2_btnB, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(button_vbox), rdo_grp2_btnC, TRUE, TRUE, 0);     gtk_container_add(GTK_CONTAINER(frm_buttons), button_vbox);     gtk_widget_show_all(frm_buttons);  }  /* The next five functions demonstrate the "event sequence" for the   * button widget.   */  void cmd_top_clicked()  {    g_print("cmd_top was clicked\n");  }  void cmd_top_pressed()  {    g_print("cmd_top was pressed\n");  }  void cmd_top_released()  {    g_print("cmd_top was released\n");  }  void cmd_top_enter()  {    g_print("cmd_top was entered\n");  }  void cmd_top_leave()  {    g_print("cmd_top was left\n");  }  void toggle_third_toggled()  {    g_print("toggle button toggled\n");  }  void toggle_third_clicked()  {    gchar *str_toggles;     static gint count_toggles = 0;     count_toggles++;     str_toggles = g_strdup_printf("%d", count_toggles);     g_print("toggle button clicked, count_toggles is %d\n", count_toggles);  /* In the following function call, note that the final argument in the   * parameter list is NULL. This is required by the function.   */  gtk_label_set_text(GTK_LABEL(lbl_second),                    g_strconcat("You toggled ", str_toggles, " time((s).", NULL));  }  void cmd_toggle_state_clicked()  {    if (TRUE == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle_third)))        MsgBox("The toggle button is DOWN.");     else        MsgBox("The toggle button is UP.");  }  void cmd_toggle_up_or_down_clicked()  {    g_print("toggling (is that a word??) toggle_third...\n");     gtk_toggle_button_toggled(GTK_TOGGLE_BUTTON(toggle_third));  }  /* Notice that the following two routines also trigger the "toggled" event. */  void cmd_toggle_up_clicked()  {  /* In this case, "set_active" means "pushed down." */  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_third), FALSE);  }  void cmd_toggle_down_clicked()  {    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle_third), TRUE);  }  void cmd_chk_button_state_clicked()  {  /* Notice what is going on here. The check button widget does not have   * a "get_active" function of its own. Therefore, in order to retrieve   * this information, you use the  toggle_button_get_active  function. The   * reason this works is that the check button is a first generation   * descendant of the toggle button. If you think about it, the check   * button is really nothing more than a different visual representation   * of the toggle button concept. This also saves time and developer   * resources because the developers don't have to create a   * "check_button_get_active" function..   *   * The GTK_TOGGLE_BUTTON macro around chk_button, below, "promotes"   * chk_button to a toggle button temporarily for the purposes of this   * function. chk_button is still a check button, but this function   * expects a toggle button. So, the macro takes care of this. */  if (TRUE == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(chk_button)))        MsgBox("The Czech button is DOWN.");     else        MsgBox("The Czech button is UP.");  }  /* =================== Text and Entry Widgets Demo Form ================*/  GtkWidget *entry_1;  GtkWidget *text_1;  GtkWidget *opt_text, *opt_entry;  GtkWidget *target_widget;  GtkWidget *spin_start, *spin_end;  void cmd_vis_true_clicked();  void cmd_vis_false_clicked();  void cmd_line_wrap_true_clicked();  void cmd_line_wrap_false_clicked();  void cmd_word_wrap_true_clicked();  void cmd_word_wrap_false_clicked();  void cmd_editable_true_clicked();  void cmd_editable_false_clicked();  void cmd_editable_get_chars_clicked();  void show_frm_text_entry()  {  /* This function creates and shows the window in   Figure 2.2   * that has the title, "Text and Entry Demo Form."   */  GtkWidget *main_hbox;     GtkWidget *text_entry_vbox, *text_vbox;     GtkWidget *lbl_entry, *lbl_text;     GtkWidget *cmd_vis_true, *cmd_vis_false;     GtkWidget *cmd_line_wrap_true, *cmd_line_wrap_false;     GtkWidget *cmd_word_wrap_true, *cmd_word_wrap_false;     GtkWidget *cmd_editable_true, *cmd_editable_false;     GtkWidget *cmd_editable_get_chars;     GtkWidget *get_chars_hbox;     GtkWidget *lbl_get_chars, *lbl_to;  /* Notice that the adjustment objects below are of   * type GtkObjectnot GtkWidget. The definition of the   * adjustment is as an object. So, declaring it here as   * an object prevents "cast-from-incorrect-type" errors   * when the program is compiled. If you declared it   * as type GtkWidget, the program would compile and run,   * but the results might not be what you expect. */  GtkObject **spin_start_adjustment, *spin_end_adjustment;     frm_text_entry = gtk_window_new(GTK_WINDOW_TOPLEVEL);     gtk_window_set_title(GTK_WINDOW(frm_text_entry),            "Text and Entry Demo Form");  /* The following three packing boxes fit together as follows:   *  main_hbox  divides the screen into left and right halves,   *  text_entry_vbox  then allows a vertical column of widgets   * on the left half, and  text_vbox  holds a GtkText widget   * on the right half of the form. */  main_hbox = gtk_hbox_new(TRUE, 0);     text_entry_vbox = gtk_vbox_new(TRUE, 0);     text_vbox = gtk_vbox_new(TRUE, 0);     lbl_text = gtk_label_new("To the right is a GtkText widget.");     lbl_entry = gtk_label_new("Below is a GtkEntry widget.");  /* The primary difference between the GtkEntry widget and   * the GtkText widget is that the entry widget is restricted to a   * single line, whereas the text widget can handle multiple lines.   *   * First, the GtkEntry widget */  entry_1 = gtk_entry_new();  /* You can set the initial string to be displayed */  gtk_entry_set_text(GTK_ENTRY(entry_1), "This is the initial text.");     cmd_vis_true = gtk_button_new_with_label("Set Entry Visibility = True");     cmd_vis_false = gtk_button_new_with_label("Set Entry Visibility = False");  /* These are the signal callbacks for the two previously created buttons. */  gtk_signal_connect(GTK_OBJECT(cmd_vis_true),           "clicked",           GTK_SIGNAL_FUNC(cmd_vis_true_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_vis_false),           "clicked",           GTK_SIGNAL_FUNC(cmd_vis_false_clicked),           NULL);  /* Now, move on to the GtkText widget. */  text_1 = gtk_text_new(NULL, NULL);     gtk_text_insert(GTK_TEXT(text_1), NULL, NULL, NULL,           "This is the initial text for the text widget. As you can see if you  resize the form, the GtkText widget will simply wrap lines at each letter, not  each word.", -1);  /* For the GtkText widget, the default is for line wrap to be ON. */  cmd_line_wrap_true = gtk_button_new_with_label("Set Text Line Wrap = True");     cmd_line_wrap_false = gtk_button_new_with_label("Set Text Line Wrap = False");     gtk_signal_connect(GTK_OBJECT(cmd_line_wrap_true),           "clicked",           GTK_SIGNAL_FUNC(cmd_line_wrap_true_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_line_wrap_false),           "clicked",           GTK_SIGNAL_FUNC(cmd_line_wrap_false_clicked),           NULL);  /* For the GtkText widget, the default is for word wrap to be OFF. */  cmd_word_wrap_true = gtk_button_new_with_label("Set Text Word Wrap = True");     cmd_word_wrap_false = gtk_button_new_with_label("Set Text Word Wrap = False");     gtk_signal_connect(GTK_OBJECT(cmd_word_wrap_true),           "clicked",           GTK_SIGNAL_FUNC(cmd_word_wrap_true_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_word_wrap_false),           "clicked",           GTK_SIGNAL_FUNC(cmd_word_wrap_false_clicked),           NULL);     opt_entry = gtk_radio_button_new_with_label(NULL, "Target is Entry Widget.");     opt_text = gtk_radio_button_new_with_label        (gtk_radio_button_group(GTK_RADIO_BUTTON(opt_entry)),         "Target is Text Widget.");     cmd_editable_true = gtk_button_new_with_label("Set Editable = True");     gtk_signal_connect(GTK_OBJECT(cmd_editable_true),           "clicked",           GTK_SIGNAL_FUNC(cmd_editable_true_clicked),           NULL);     cmd_editable_false = gtk_button_new_with_label("Set Editable = False");     gtk_signal_connect(GTK_OBJECT(cmd_editable_false),           "clicked",           GTK_SIGNAL_FUNC(cmd_editable_false_clicked),           NULL);  /* Below are the spin button controls used to demonstrate the   * extraction of a portion of text from a gtk_editable   * widget.   *   * First, you need a small horizontal box to contain the widgets. */  get_chars_hbox = gtk_hbox_new(FALSE, 0);  /* The best way to use a spin button widget is to use it with an   * adjustment object (see the object declarations at the top of this   * function). An adjustment object abstracts the behavior out of   * the spin button, allowing you to set the min, max, default, etc.,   * independent of the spin widget. Note that the parameters to the   *  gtk_adjustment_new  function below are of type gfloat, but using   * integers also works without error or warning.   *   * Another note: You can use the same adjustment object for multiple   * spin buttons, but then they will behave as if they are tied   * to one another, which means that when you adjust one, the other will   * mirror that action. */  spin_start_adjustment = gtk_adjustment_new(1.0, 1.0, 99.0, 1.0, 1.0, 1.0);     spin_end_adjustment = gtk_adjustment_new(1, 2, 99, 1, 1, 1);     lbl_get_chars = gtk_label_new("Get chars");     spin_start = gtk_spin_button_new(GTK_ADJUSTMENT(spin_start_adjustment),                                      1.0, 0);       lbl_to = gtk_label_new(" to ");     spin_end = gtk_spin_button_new(GTK_ADJUSTMENT(spin_end_adjustment), 1.0, 0);     cmd_editable_get_chars = gtk_button_new_with_label("Get selected chars");     gtk_signal_connect(GTK_OBJECT(cmd_editable_get_chars),           "clicked",           GTK_SIGNAL_FUNC(cmd_editable_get_chars_clicked),           NULL);  /* Now to build the form and then display it. */  gtk_box_pack_start(GTK_BOX(get_chars_hbox), lbl_get_chars, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(get_chars_hbox), spin_start, FALSE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(get_chars_hbox), lbl_to, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(get_chars_hbox), spin_end, FALSE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),lbl_text,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),lbl_entry,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),entry_1,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_vis_true,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_vis_false,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_line_wrap_true,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_line_wrap_false,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_word_wrap_true,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_word_wrap_false,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),opt_entry,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),opt_text,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_editable_true,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_editable_false,TRUE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),get_chars_hbox,FALSE,TRUE,0);     gtk_box_pack_start(GTK_BOX(text_entry_vbox),cmd_editable_get_chars,                        TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(text_vbox), text_1, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(main_hbox), text_entry_vbox, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(main_hbox), text_vbox, TRUE, TRUE, 0);     gtk_container_add(GTK_CONTAINER(frm_text_entry), main_hbox);     gtk_widget_show_all(frm_text_entry);  }  void cmd_vis_true_clicked()  {    gtk_entry_set_visibility(GTK_ENTRY(entry_1), TRUE);     g_print("Visibility for entry_1 has been set True.\n");  }  void cmd_vis_false_clicked()  {    gtk_entry_set_visibility(GTK_ENTRY(entry_1), FALSE);     g_print("Visibility for entry_1 has been set False.\n");  }  void cmd_line_wrap_true_clicked()  {    gtk_text_set_line_wrap(GTK_TEXT(text_1), TRUE);  }  void cmd_line_wrap_false_clicked()  {    gtk_text_set_line_wrap(GTK_TEXT(text_1), FALSE);  }  void cmd_word_wrap_true_clicked()  {    gtk_text_set_word_wrap(GTK_TEXT(text_1), TRUE);  }  void cmd_word_wrap_false_clicked()  {    gtk_text_set_word_wrap(GTK_TEXT(text_1), FALSE);  }  void cmd_editable_true_clicked()  {    if (TRUE == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_entry)))     {       gtk_editable_set_editable(GTK_EDITABLE(entry_1), TRUE);        MsgBox("The entry widget\nat top left\nis now editable.");     }     else     {       gtk_editable_set_editable(GTK_EDITABLE(text_1), TRUE);        MsgBox("The text widget\nis now editable.");     }  }  void cmd_editable_false_clicked()  {    if (TRUE == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_entry)))     {       gtk_editable_set_editable(GTK_EDITABLE(entry_1), FALSE);        MsgBox("The entry widget\nat top left\nis now\nNOT\neditable.");     }     else     {       gtk_editable_set_editable(GTK_EDITABLE(text_1), FALSE);        MsgBox("The text widget\nis now\nNOT\neditable.");     }    }  void cmd_editable_get_chars_clicked()  {    if (TRUE == gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(opt_entry)))     {  /* Note: Because the gtk_editable_get_chars does not include   * the character in the second parameter, you have to move it   * back one space so as to be inclusive. For example, if the   * user has selected characters 1 through 4, he expects to see   * character 1, but the default behavior of the call below is   * to show only characters 2 through 4.   * One of the advantages to using the spin button controls here   * is that they already have functions that return integers.   * If you were to use an Entry or Text widget, you would have   * to do the conversions yourself./*  MsgBox(g_strconcat("The chars from the\nentry widget are: ",                gtk_editable_get_chars(GTK_EDITABLE(entry_1),                gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_start)) - 1,                gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_end))),                NULL));     }     else     {    MsgBox(g_strconcat("The chars from the\ntext widget are: ",              gtk_editable_get_chars(GTK_EDITABLE(text_1),              gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_start)) - 1,              gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(spin_end))),              NULL));     }  }  /* ====================== List Widgets Demo ===========================*/  void cmd_add_checkbox_clicked();  void cmd_add_pixmap_clicked();  void cmd_SINGLE_clicked();  void cmd_BROWSE_clicked();  void cmd_MULTIPLE_clicked();  void cmd_EXTENDED_clicked();  void cmd_prepend_clicked();  void cmd_append_clicked();  void cmd_insert_row_2_clicked();  void cmd_set_text_clicked();  void cmd_set_pixmap_clicked();  void cmd_set_pixtext_clicked();  void cmd_sort_clicked();  GtkWidget *list_left;  GtkWidget *clist_right;  /* These arrays are your data for the CList.   * Note that the number of elements   * must match that of the CList widget.   */  gchar *a_row[3] = {"blank", "", ""};  void show_frm_list_widgets()  {  /* This function creates and displays the   * window titled "List and CList Demo Form"   * that's shown in   Figure 2.2   .   */  GtkWidget *lists_hbox;  /* The List widget is on the left, and the CList widget is on the right. */  GtkWidget *lbl_list_box, *lbl_clist_box;     GtkWidget *vbox_left, *vbox_right;     GtkWidget *cmd_SINGLE, *cmd_BROWSE, *cmd_MULTIPLE, *cmd_EXTENDED;     GtkWidget *cmd_add_checkbox;     GtkWidget *cmd_add_pixmap;     GtkWidget *cmd_append, *cmd_prepend, *cmd_insert_row_2;     GtkWidget *cmd_set_text, *cmd_set_pixmap, *cmd_set_pixtext;     GtkWidget *cmd_sort;  /* Next is an array of column headers for the CList widget. */  gchar *col_heads[3] = {"Author", "Title", "Year"};     GList *list_box_items = NULL;     frm_list_widgets = gtk_window_new(GTK_WINDOW_TOPLEVEL);     gtk_window_set_title(GTK_WINDOW(frm_list_widgets),                          "List and CList Demo Form");  /* These are the main widgets on the form. */  lists_hbox = gtk_hbox_new(TRUE, 0);     lbl_list_box = gtk_label_new("Below is a List Box.");     lbl_clist_box = gtk_label_new("... and this is a CList Box.");     vbox_left = gtk_vbox_new(FALSE, 0);     vbox_right = gtk_vbox_new(FALSE, 0);     list_left = gtk_list_new();  /* Now, concentrate on the List widget.   *   * The great thing about the List widget is that you can   * have any widget as a child widget. "ANY widget?" Well,,   * that's what they claim. Normally, this will be used   * with label widgets, pixmaps (Linux' version of icons), and   * check boxes. Those are the things you expect to see   * in a list box. "But ANY widget? What about a window?   * How about a List widget filled with CList widgets?"   * I have never tried to do anything like that before,   * and I cannot think of any kind of business application   * where that would make a good user interface, but you   * never know. If you get a chance to try something   * nutso like that, be sure to drop me a line and let   * me know how it turned out!   *   * Okay, here is the deal with list boxes. The list of   * items in the list box is actually a separate object   * (a linked list) from the list box itself.   * At the top of this function, you defined a GList object named   * list_box_items. This GList is filled with "list   * items." Now,, because a "list of labels" is so   * common, GTK+ has a designated function just for adding   * "list item" objects: gtk_list_item_new_with_label().   * So you can create a GList and fill it with GtkListItem   * widgets   */  list_box_items = g_list_append(list_box_items,              gtk_list_item_new_with_label("list item 1"));     list_box_items = g_list_append(list_box_items,              gtk_list_item_new_with_label("list item 2"));     list_box_items = g_list_append(list_box_items,              gtk_list_item_new_with_label("list item 3"));  /* Once you have the GList of GtkListItem widgets, you take   * that whole list and smack it into the GtkListBox widget   * that you created:   */  g_print("starting initial list append...\n");     gtk_list_append_items(GTK_LIST(list_left), list_box_items);  /* So, that's the easy caseall label widgets. Now let's see   * if you can get a few other things in there too   *   * Add a checkbox, too.   */  cmd_add_checkbox = gtk_button_new_with_label("Add a checkbox.");     gtk_signal_connect(GTK_OBJECT(cmd_add_checkbox),           "clicked",           GTK_SIGNAL_FUNC(cmd_add_checkbox_clicked),           NULL);  /* And how about a pixmap? */  cmd_add_pixmap = gtk_button_new_with_label("Add a pixmap.");     gtk_signal_connect(GTK_OBJECT(cmd_add_pixmap),           "clicked",           GTK_SIGNAL_FUNC(cmd_add_pixmap_clicked),           NULL);  /* And how about some command buttons for setting the   * selection mode of the List widget? */  cmd_SINGLE = gtk_button_new_with_label("Set selection mode SINGLE");     cmd_BROWSE = gtk_button_new_with_label("Set selection mode BROWSE");     cmd_MULTIPLE = gtk_button_new_with_label("Set selection mode MULTIPLE");     cmd_EXTENDED = gtk_button_new_with_label("Set selection mode EXTENDED");     gtk_signal_connect(GTK_OBJECT(cmd_SINGLE),           "clicked",           GTK_SIGNAL_FUNC(cmd_SINGLE_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_BROWSE),           "clicked",           GTK_SIGNAL_FUNC(cmd_BROWSE_clicked),           NULL);     gtk_signal_connect(GTK_OBJECT(cmd_MULTIPLE),           "clicked",           GTK_SIGNAL_FUNC(cmd_MULTIPLE_clicked),          NULL);     gtk_signal_connect(GTK_OBJECT(cmd_EXTENDED),           "clicked",           GTK_SIGNAL_FUNC(cmd_EXTENDED_clicked),           NULL);  /* Finally, add the CList widget.   *   * The CList widget is the closest GTK+ comes to a "data   * control"; the problem is that you have to supply your own   * database connectivity.   *   * Unlike the List widget, which can accept almost any   * child widget to populate the list box, the CList   * widget is limited to text and pixmaps.   *   * Also note that the CList widget has the same   * selection modes as the List widget.   */  clist_right = gtk_clist_new_with_titles(3, col_heads);  /* Populating a CList widget is pretty simple, as you can see. */  gtk_clist_append(GTK_CLIST(clist_right), a_row);     cmd_append = gtk_button_new_with_label("Append Row");     gtk_signal_connect(GTK_OBJECT(cmd_append),           "clicked",           GTK_SIGNAL_FUNC(cmd_append_clicked),           NULL);     cmd_prepend = gtk_button_new_with_label("Prepend Row");     gtk_signal_connect(GTK_OBJECT(cmd_prepend),           "clicked",           GTK_SIGNAL_FUNC(cmd_prepend_clicked),           NULL);     cmd_insert_row_2 = gtk_button_new_with_label("Insert to Row 2");     gtk_signal_connect(GTK_OBJECT(cmd_insert_row_2),           "clicked",           GTK_SIGNAL_FUNC(cmd_insert_row_2_clicked),           NULL);     cmd_set_text = gtk_button_new_with_label("Set Row 3 Col 1 to Text");     gtk_signal_connect(GTK_OBJECT(cmd_set_text),           "clicked",           GTK_SIGNAL_FUNC(cmd_set_text_clicked),           NULL);     cmd_set_pixmap = gtk_button_new_with_label("Set Row 3 Col 2 to Pixmap");     gtk_signal_connect(GTK_OBJECT(cmd_set_pixmap),           "clicked",           GTK_SIGNAL_FUNC(cmd_set_pixmap_clicked),           NULL);     cmd_set_pixtext = gtk_button_new_with_label("Set Row 3 Col 3 to PixText");     gtk_signal_connect(GTK_OBJECT(cmd_set_pixtext),           "clicked",           GTK_SIGNAL_FUNC(cmd_set_pixtext_clicked),           NULL);     cmd_sort = gtk_button_new_with_label("Sort on Column 1");     gtk_signal_connect(GTK_OBJECT(cmd_sort),           "clicked",           GTK_SIGNAL_FUNC(cmd_sort_clicked),           NULL);  /* Finally, add the interface. As before, you are going to pack the   * widgets "from the inside out." */  gtk_box_pack_start(GTK_BOX(vbox_left), lbl_list_box, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), list_left, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_add_checkbox, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_add_pixmap, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_SINGLE, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_BROWSE, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_MULTIPLE, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_left), cmd_EXTENDED, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), lbl_clist_box, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), clist_right, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_append, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_prepend, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_insert_row_2, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_set_text, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_set_pixmap, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_set_pixtext, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(vbox_right), cmd_sort, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(lists_hbox), vbox_left, TRUE, TRUE, 0);     gtk_box_pack_start(GTK_BOX(lists_hbox), vbox_right, TRUE, TRUE, 0);     gtk_container_add(GTK_CONTAINER(frm_list_widgets), lists_hbox);     gtk_widget_show_all(frm_list_widgets);  }  void cmd_add_checkbox_clicked()  {    GtkWidget *chk_box_item;     GtkWidget *list_item;     chk_box_item = gtk_check_button_new_with_label("Check box item");     list_item = gtk_list_item_new();     gtk_container_add(GTK_CONTAINER(list_item), chk_box_item);     gtk_container_add(GTK_CONTAINER(list_left), list_item);  /* In essence, the line below "refreshes" the form.. */  gtk_widget_show_all(frm_list_widgets);  }  /* Looks like it is time to introduce pixmaps because one will be needed   * for the next function call.   *   * Note that the pixmap could just as easily have been put in a   * separate file and included with an #include statement.   *   * Here is how to read a pixmap file:   *   * The first line ("26 7 2 1") gives the dimensions of the pixmap.   * In this case, that means 26 columns by 7 rows, 2 color values,   * and 1 character is needed to display a color.   *   * The next two lines define the color values. "None" is for   * transparency, and the other is in hex.   *   * After that, the rows are laid out with parentheses around them,   * and the values within the parentheses must correspond to one   * of the colors listed.   */  static const gchar *pixmap_xpm[] == {    "26 7 2 1",     "    c None",     ".   c #AA8800",  /*123456789.123456789.123456 <-- for spacing */  "                          ",     " ..  . .   . .   .  .  .. ",     " . . .  . .  .. .. . . . .",     " ..  .   .   . . . ... .. ",     " .   .  . .  .   . . . .  ",     " .   . .   . .   . . . .  ",     "                          "  };  /* Important Safety Tip: The semicolon on the preceding   * line is necessary because the entire pixmap structure   * above is a single variable. If you don't include the   * pixmap, you will get a "parse error before" message   * when you compile.   *   * The pixmap above draws out the word "PIXMAP".   */  void cmd_add_pixmap_clicked()  {    GtkWidget *my_pixmap;     GtkWidget *list_item;  /* The following objects are needed for drawing a pixmap */  GdkBitmap *a_bitmap;     GdkPixmap *a_pixmap;     a_pixmap = gdk_pixmap_colormap_create_from_xpm_d         (NULL,         gdk_colormap_get_system(),         &a_bitmap,         NULL,         (gchar **) pixmap_xpm);     my_pixmap = gtk_pixmap_new(a_pixmap, a_bitmap);     list_item = gtk_list_item_new();     gtk_container_add(GTK_CONTAINER(list_item), my_pixmap);     gtk_container_add(GTK_CONTAINER(list_left), list_item);     gtk_widget_show_all(frm_list_widgets);  }  void cmd_SINGLE_clicked()  {  /* SINGLE mode allows one selection only. You must click and release   * on the same item to select it. Click, hold, and drag changes the   * focus, not the selection. The item is selected on the mouse up event.   * Ctrl and Shift modifiers have no effect.   */  gtk_list_set_selection_mode(GTK_LIST(list_left), GTK_SELECTION_SINGLE);  }  void cmd_BROWSE_clicked()  {  /* Only one selection is allowed. The item is selected on mouse down   * event. Click, hold, and drag changes the selection. Ctrl and Shift   * modifiers have no effect.   */  gtk_list_set_selection_mode(GTK_LIST(list_left), GTK_SELECTION_BROWSE);  }  void cmd_MULTIPLE_clicked()  {  /* Multiple selections are allowed; other behaviors are similar to SINGLE   * mode. Mouse up event selects, and you must click and release on the   * same item to select. Click, hold, and drag changes focus, not   * selection. Ctrl and Shift modifiers have no effect.   */  gtk_list_set_selection_mode(GTK_LIST(list_left), GTK_SELECTION_MULTIPLE);  }  void cmd_EXTENDED_clicked()  {  /* Multiple selection; selection is on the mouse down event. Click,   * hold, and drag selects all list items that come under the mouse.   * Ctrl and Shift modifiers behave as expected: Shift selects all between   * previous mouse click and current mouse click, Ctrl selects item that is   * currently under the mouse in addition to previously selected items.   */  gtk_list_set_selection_mode(GTK_LIST(list_left), GTK_SELECTION_EXTENDED);  }  void cmd_prepend_clicked()  {    a_row[0] = "Ayn Rand';     a_row[1] = "Atlas Shrugged";     a_row[2] = "1957";     gtk_clist_prepend(GTK_CLIST(clist_right), a_row);     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  void cmd_append_clicked()  {    a_row[0] = "Hermann Hesse";     a_row[1] = "Steppenwolf";     a_row[2] = "1898";     gtk_clist_append(GTK_CLIST(clist_right), a_row);     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  void cmd_insert_row_2_clicked()  {    a_row[0] = "Jack Kerouac";     a_row[1] = "On The Road";     a_row[2] = "1958";  /* The 1 in the insert below is really "row 2";   * the second parameter is zero-based.   */  gtk_clist_insert(GTK_CLIST(clist_right), 1, a_row);     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  /* For the next three function calls, which have to do with   * setting text or pixmaps in a CList widget, the following is true:   *   * The row and column referenced need to already exist   * (at least in this example) because you are not checking   * return values for errors.   *   * Also note that a "2" referencing a row is actually   * "row 3" because the CList widget's row and column   * references are zero-based.   */  void cmd_set_text_clicked()  {    gtk_clist_set_text(GTK_CLIST(clist_right), 2, 0, "Text");     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  void cmd_set_pixmap_clicked()  {    GtkWidget *my_pixmap;     GdkBitmap *a_bitmap;     GdkPixmap *a_pixmap;     a_pixmap = gdk_pixmap_colormap_create_from_xpm_d         (NULL,         gdk_colormap_get_system(),         &a_bitmap,         NULL,         (gchar **) pixmap_xpm);     my_pixmap = gtk_pixmap_new(a_pixmap, a_bitmap);     gtk_clist_set_pixmap(GTK_CLIST(clist_right), 2, 1, a_pixmap, a_bitmap);     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  void cmd_set_pixtext_clicked()  {    GtkWidget *my_pixmap;     GdkBitmap *a_bitmap;     GdkPixmap *a_pixmap;     a_pixmap = gdk_pixmap_colormap_create_from_xpm_d         (NULL,         gdk_colormap_get_system(),         &a_bitmap,         NULL,         (gchar **) pixmap_xpm);     my_pixmap = gtk_pixmap_new(a_pixmap, a_bitmap);     gtk_clist_set_pixtext(GTK_CLIST(clist_right), 2, 2, "Text",           10, a_pixmap, a_bitmap);     gtk_clist_columns_autosize(GTK_CLIST(clist_right));  }  void cmd_sort_clicked()  {    gtk_clist_set_sort_column(GTK_CLIST(clist_right), 0);     gtk_clist_sort(GTK_CLIST(clist_right));  /* Note that if the CList is to be sorted automatically each time   * the data changes, there is a gtk_clist_set_auto_sort() function.   */  } 

Compiling with gcc

As with the C program demonstrating MySQL connectivity in Chapter 1 (Listing 1.3) and the HelloWorld program (Listing 2.1), you can compile from the command line, from a shell script, or from a Makefile. The choice is yours. This compile is not different from the compile done for HelloWorld, except for the *.c filename, of course. From the command line, send:

 %gcc -Wall -g listing.2.2.c `gtk-config --cflags --libs` 

Figure 2.2 shows Listing 2.2 running, with all the window widgets visible. Notice the Text widget in the Text and Entry Demo Form window; the curly arrows at the end of the lines indicate that the text widget is wrapping the text, so the user doesnt have to enter hard returns as part of the text he or she is entering. If you compile and run the program, you will see other things, such as the List widget showing pixmaps.

Figure 2.2. Listing 2.2, the Basic Widget Tour, running.
graphics/02fig02.gif
only for RuBoard - do not distribute or recompile


MySQL Building User Interfaces
MySQL: Building User Interfaces (Landmark)
ISBN: 073571049X
EAN: 2147483647
Year: 2001
Pages: 119

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net