Usando la Biblioteca libgnomeui

Además de GnomeApp, la biblioteca libgnomeui contiene un gran número de otros objetos y widgets, incluyendo diálogos estándar, manejo de sesiones, MDI y otros útiles widgets. También contiene el widget GnomeCanvas que merece un trato aparte. Esta es la biblioteca que hace más fácil la vida de los programadores. Es importante que use estos widgets mejor que simplemente los de GTK+, ya que estos widgets le darán la consistencia y las características que espera el usuario de aplicaciones GNOME.

Iconos Predefinidos

Muchas veces deseará usar botones y opciones estándares (como pueden ser Abrir o Guardar como...), y también deseará proporcionar iconos en las opciones del menú, con los botones de la barra de herramientas o los botones de las ventanas de diálogo; para facilitar la navegación puede usar algunos de los iconos definidos de gnome-libs. A estos iconos se les llama iconos predefinidos o iconos por defecto. Ya ha visto un ejemplo de cómo usar iconos predefinidos en menús y barras de herramientas (usando la definición apropiada en libgnomeui/ gnome-stock.h). También hay botones predefinidos pudiendo usar un widget de botón basado en una descripción predefinida.

Aquí hay una lista de los iconos predefinidos normales de GNOME, estos tienen un tamaño normalizado para su uso en barras de herramientas y en otros lugares donde necesite un icono con tamaño normalizado. Están dados como definiciones de cadenas de caracteres constantes y su significado debería ser obvio.

#define GNOME_STOCK_PIXMAP_NEW         "New"
#define GNOME_STOCK_PIXMAP_OPEN        "Open"
#define GNOME_STOCK_PIXMAP_CLOSE       "Close"
#define GNOME_STOCK_PIXMAP_REVERT      "Revert"
#define GNOME_STOCK_PIXMAP_SAVE        "Save"
#define GNOME_STOCK_PIXMAP_SAVE_AS     "Save As"
#define GNOME_STOCK_PIXMAP_CUT         "Cut"
#define GNOME_STOCK_PIXMAP_COPY        "Copy"
#define GNOME_STOCK_PIXMAP_PASTE       "Paste"
#define GNOME_STOCK_PIXMAP_PROPERTIES  "Properties"
#define GNOME_STOCK_PIXMAP_PREFERENCES "Preferences"
#define GNOME_STOCK_PIXMAP_HELP        "Help"
#define GNOME_STOCK_PIXMAP_SCORES      "Scores"
#define GNOME_STOCK_PIXMAP_PRINT       "Print"
#define GNOME_STOCK_PIXMAP_SEARCH      "Search"
#define GNOME_STOCK_PIXMAP_SRCHRPL     "Search/Replace"
#define GNOME_STOCK_PIXMAP_BACK        "Back"
#define GNOME_STOCK_PIXMAP_FORWARD     "Forward"
#define GNOME_STOCK_PIXMAP_FIRST       "First"
#define GNOME_STOCK_PIXMAP_LAST        "Last"
#define GNOME_STOCK_PIXMAP_HOME        "Home"
#define GNOME_STOCK_PIXMAP_STOP        "Stop"
#define GNOME_STOCK_PIXMAP_REFRESH     "Refresh"
#define GNOME_STOCK_PIXMAP_UNDO        "Undo"
#define GNOME_STOCK_PIXMAP_REDO        "Redo"
#define GNOME_STOCK_PIXMAP_TIMER       "Timer"
#define GNOME_STOCK_PIXMAP_TIMER_STOP  "Timer Stopped"
#define GNOME_STOCK_PIXMAP_MAIL        "Mail"
#define GNOME_STOCK_PIXMAP_MAIL_RCV    "Receive Mail"
#define GNOME_STOCK_PIXMAP_MAIL_SND    "Send Mail"
#define GNOME_STOCK_PIXMAP_MAIL_RPL    "Reply to Mail"
#define GNOME_STOCK_PIXMAP_MAIL_FWD    "Forward Mail"
#define GNOME_STOCK_PIXMAP_MAIL_NEW    "New Mail"
#define GNOME_STOCK_PIXMAP_TRASH       "Trash"
#define GNOME_STOCK_PIXMAP_TRASH_FULL  "Trash Full"
#define GNOME_STOCK_PIXMAP_UNDELETE    "Undelete"
#define GNOME_STOCK_PIXMAP_SPELLCHECK  "Spellchecker"
#define GNOME_STOCK_PIXMAP_MIC         "Microphone"
#define GNOME_STOCK_PIXMAP_LINE_IN     "Line In"
#define GNOME_STOCK_PIXMAP_CDROM       "Cdrom"
#define GNOME_STOCK_PIXMAP_VOLUME      "Volume"
#define GNOME_STOCK_PIXMAP_BOOK_RED    "Book Red"
#define GNOME_STOCK_PIXMAP_BOOK_GREEN  "Book Green"
#define GNOME_STOCK_PIXMAP_BOOK_BLUE   "Book Blue"
#define GNOME_STOCK_PIXMAP_BOOK_YELLOW "Book Yellow"
#define GNOME_STOCK_PIXMAP_BOOK_OPEN   "Book Open"
#define GNOME_STOCK_PIXMAP_ABOUT       "About"
#define GNOME_STOCK_PIXMAP_QUIT        "Quit"
#define GNOME_STOCK_PIXMAP_MULTIPLE    "Multiple"
#define GNOME_STOCK_PIXMAP_NOT         "Not"
#define GNOME_STOCK_PIXMAP_CONVERT     "Convert"
#define GNOME_STOCK_PIXMAP_JUMP_TO     "Jump To"
#define GNOME_STOCK_PIXMAP_UP          "Up"
#define GNOME_STOCK_PIXMAP_DOWN        "Down"
#define GNOME_STOCK_PIXMAP_TOP         "Top"
#define GNOME_STOCK_PIXMAP_BOTTOM      "Bottom"
#define GNOME_STOCK_PIXMAP_ATTACH      "Attach"
#define GNOME_STOCK_PIXMAP_INDEX       "Index"
#define GNOME_STOCK_PIXMAP_FONT        "Font"
#define GNOME_STOCK_PIXMAP_EXEC        "Exec"

#define GNOME_STOCK_PIXMAP_ALIGN_LEFT  "Left"
#define GNOME_STOCK_PIXMAP_ALIGN_RIGHT "Right"
#define GNOME_STOCK_PIXMAP_ALIGN_CENTER "Center"
#define GNOME_STOCK_PIXMAP_ALIGN_JUSTIFY "Justify"

#define GNOME_STOCK_PIXMAP_TEXT_BOLD    "Bold"
#define GNOME_STOCK_PIXMAP_TEXT_ITALIC  "Italic"
#define GNOME_STOCK_PIXMAP_TEXT_UNDERLINE "Underline"
#define GNOME_STOCK_PIXMAP_TEXT_STRIKEOUT "Strikeout"

#define GNOME_STOCK_PIXMAP_EXIT        GNOME_STOCK_PIXMAP_QUIT

Si quiere usarlo fuera de GnomeUIInfo, necesita obtener el widget con el pixmap. Lo que se hace es llamar a la función gnome_stock_pixmap_widget con su ventana principal como primer argumento (por eso que puede copiar su estilo) y el nombre del icono (uno de los definidos antes) como segundo argumento. Esto devuelve un nuevo widget que puede usar como un pixmap.

Para los menús puede usar la variedad _MENU_ de los pixmaps predefinidos. Estos son más pequeños y son lo que debe usar para los elementos del menú por defecto en su definición de GnomeUIInfo.

#define GNOME_STOCK_MENU_BLANK        "Menu_"
#define GNOME_STOCK_MENU_NEW          "Menu_New"
#define GNOME_STOCK_MENU_SAVE         "Menu_Save"
#define GNOME_STOCK_MENU_SAVE_AS      "Menu_Save As"
#define GNOME_STOCK_MENU_REVERT       "Menu_Revert"
#define GNOME_STOCK_MENU_OPEN         "Menu_Open"
#define GNOME_STOCK_MENU_CLOSE        "Menu_Close"
#define GNOME_STOCK_MENU_QUIT         "Menu_Quit"
#define GNOME_STOCK_MENU_CUT          "Menu_Cut"
#define GNOME_STOCK_MENU_COPY         "Menu_Copy"
#define GNOME_STOCK_MENU_PASTE        "Menu_Paste"
#define GNOME_STOCK_MENU_PROP         "Menu_Properties"
#define GNOME_STOCK_MENU_PREF         "Menu_Preferences"
#define GNOME_STOCK_MENU_ABOUT        "Menu_About"
#define GNOME_STOCK_MENU_SCORES       "Menu_Scores"
#define GNOME_STOCK_MENU_UNDO         "Menu_Undo"
#define GNOME_STOCK_MENU_REDO         "Menu_Redo"
#define GNOME_STOCK_MENU_PRINT        "Menu_Print"
#define GNOME_STOCK_MENU_SEARCH       "Menu_Search"
#define GNOME_STOCK_MENU_SRCHRPL      "Menu_Search/Replace"
#define GNOME_STOCK_MENU_BACK         "Menu_Back"
#define GNOME_STOCK_MENU_FORWARD      "Menu_Forward"
#define GNOME_STOCK_MENU_FIRST        "Menu_First"
#define GNOME_STOCK_MENU_LAST         "Menu_Last"
#define GNOME_STOCK_MENU_HOME         "Menu_Home"
#define GNOME_STOCK_MENU_STOP         "Menu_Stop"
#define GNOME_STOCK_MENU_REFRESH      "Menu_Refresh"
#define GNOME_STOCK_MENU_MAIL         "Menu_Mail"
#define GNOME_STOCK_MENU_MAIL_RCV     "Menu_Receive Mail"
#define GNOME_STOCK_MENU_MAIL_SND     "Menu_Send Mail"
#define GNOME_STOCK_MENU_MAIL_RPL     "Menu_Reply to Mail"
#define GNOME_STOCK_MENU_MAIL_FWD     "Menu_Forward Mail"
#define GNOME_STOCK_MENU_MAIL_NEW     "Menu_New Mail"
#define GNOME_STOCK_MENU_TRASH        "Menu_Trash"
#define GNOME_STOCK_MENU_TRASH_FULL   "Menu_Trash Full"
#define GNOME_STOCK_MENU_UNDELETE     "Menu_Undelete"
#define GNOME_STOCK_MENU_TIMER        "Menu_Timer"
#define GNOME_STOCK_MENU_TIMER_STOP   "Menu_Timer Stopped"
#define GNOME_STOCK_MENU_SPELLCHECK   "Menu_Spellchecker"
#define GNOME_STOCK_MENU_MIC          "Menu_Microphone"
#define GNOME_STOCK_MENU_LINE_IN      "Menu_Line In"
#define GNOME_STOCK_MENU_CDROM        "Menu_Cdrom"
#define GNOME_STOCK_MENU_VOLUME       "Menu_Volume"
#define GNOME_STOCK_MENU_BOOK_RED     "Menu_Book Red"
#define GNOME_STOCK_MENU_BOOK_GREEN   "Menu_Book Green"
#define GNOME_STOCK_MENU_BOOK_BLUE    "Menu_Book Blue"
#define GNOME_STOCK_MENU_BOOK_YELLOW  "Menu_Book Yellow"
#define GNOME_STOCK_MENU_BOOK_OPEN    "Menu_Book Open"
#define GNOME_STOCK_MENU_CONVERT      "Menu_Convert"
#define GNOME_STOCK_MENU_JUMP_TO      "Menu_Jump To"
#define GNOME_STOCK_MENU_UP           "Menu_Up"
#define GNOME_STOCK_MENU_DOWN         "Menu_Down"
#define GNOME_STOCK_MENU_TOP          "Menu_Top"
#define GNOME_STOCK_MENU_BOTTOM       "Menu_Bottom"
#define GNOME_STOCK_MENU_ATTACH       "Menu_Attach"
#define GNOME_STOCK_MENU_INDEX        "Menu_Index"
#define GNOME_STOCK_MENU_FONT         "Menu_Font"
#define GNOME_STOCK_MENU_EXEC         "Menu_Exec"

#define GNOME_STOCK_MENU_ALIGN_LEFT     "Menu_Left"
#define GNOME_STOCK_MENU_ALIGN_RIGHT    "Menu_Right"
#define GNOME_STOCK_MENU_ALIGN_CENTER   "Menu_Center"
#define GNOME_STOCK_MENU_ALIGN_JUSTIFY  "Menu_Justify"

#define GNOME_STOCK_MENU_TEXT_BOLD      "Menu_Bold"
#define GNOME_STOCK_MENU_TEXT_ITALIC    "Menu_Italic"
#define GNOME_STOCK_MENU_TEXT_UNDERLINE "Menu_Underline"
#define GNOME_STOCK_MENU_TEXT_STRIKEOUT "Menu_Strikeout"

#define GNOME_STOCK_MENU_EXIT     GNOME_STOCK_MENU_QUIT

Si está construyendo el menú usted mismo y quiere utilizar un elemento de menú con icono y etiqueta predefinida, puede usar la función gnome_stock_menu_item. Toma el tipo de icono predefinido (uno de los definidos arriba) como primer argumento, el texto del menú como segundo argumento, y devuelve un widget recién creado de elemento de menú.

Hay botones predefinidos. Estos están para el uso en ventanas de diálogo (ver más adelante).

#define GNOME_STOCK_BUTTON_OK     "Button_Ok"
#define GNOME_STOCK_BUTTON_CANCEL "Button_Cancel"
#define GNOME_STOCK_BUTTON_YES    "Button_Yes"
#define GNOME_STOCK_BUTTON_NO     "Button_No"
#define GNOME_STOCK_BUTTON_CLOSE  "Button_Close"
#define GNOME_STOCK_BUTTON_APPLY  "Button_Apply"
#define GNOME_STOCK_BUTTON_HELP   "Button_Help"
#define GNOME_STOCK_BUTTON_NEXT   "Button_Next"
#define GNOME_STOCK_BUTTON_PREV   "Button_Prev"
#define GNOME_STOCK_BUTTON_UP     "Button_Up"
#define GNOME_STOCK_BUTTON_DOWN   "Button_Down"
#define GNOME_STOCK_BUTTON_FONT   "Button_Font"

Para tomar un widget de botón con el texto e icono de predefinido, puede usar la función gnome_stock_button con el tipo de botón (uno de los definidos arriba) como argumento. Ahora bien, algunas veces querrá hacer una mezcla de botones predefinidos y ordinarios, para conseguirlo llame a la función gnome_stock_or_ordinary_button con el tipo de botón predefinido y un texto para la etiqueta del botón. La función revisa si es una de las cadenas anteriores, y si no está crea un widget de botón ordinario con el texto como etiqueta. Aquí hay un ejemplo, crea tres botones empaquetándolos en una caja (no incluimos el código para hacer la caja), dos de los botones están predefinidos y el otro es normal:

GtkWidget *w;
GtkWidget *caja;
int i;
char *botones[]={
        GNOME_STOCK_BUTTON_OK,
        GNOME_STOCK_BUTTON_CANCEL,
        "Foo",
        NULL
};
...
/* bucle a través de todas las cadenas en el vector de botones*/
for(i = 0; botones[i] != NULL; i++) {
        /* creamos el botón, predefinido u ordinario */
        w = gnome_stock_or_ordinary_button(botones[i]);

        /* Lo mostramos y lo empaquetamos */
        gtk_widget_show(w);
        gtk_box_pack_start(GTK_BOX(caja),w,FALSE,FALSE,0);
 /* Deberíamos unir las señales y más cosas aquí */
        ...
}

Diálogos

Diálogos Genéricos

Si necesita crear su propio diálogo personalizado, gnome-dialog es el camino para hacerlo. Puede soportar tanto diálogos modales como no modales. De todas formas, es definitivamente mucho más cómodo para los usuarios de su programa si usa diálogos no modales, si es posible, porque los diálogos no modales tienden a tener problemas asociados, y algunas veces pueden causar errores extraños. Por ejemplo, si un diálogo no modal se asocia con una ventana, sería bueno conectar la señal destroy de la ventana para que también destruya la ventana del diálogo, de otra manera se podría producir un error al actuar sobre un documento o ventana que ya no existe. Sin embargo, los diálogos modales (los que son más fáciles de programar) normalmente son bastante engorrosos de usar, por eso evítelos si puede.

Para hacer un nuevo widget GnomeDialog, use la función gnome_dialog_new. Se pasa el título del diálogo como primer argumento, y después múltiples argumentos, con los títulos de los botones, terminando con un NULL. Los títulos de los botones también pueden ser las definiciones GNOME_STOCK_BUTTON_*, si es que desea botones predefinidos en su diálogo. Ahora necesita dotar de un contenido al diálogo, el diálogo se crea con una caja vertical (GtkVBox) para que usted lo use simplemente con GNOME_DIALOG(dialog)->vbox. Con esto puede introducir el contenido.

Debería también establecer la ventana principal de la aplicación (su GnomeApp) como el padre del diálogo. Esto permite al gestor de ventanas manejar la ventana más apropiadamente que una simple ventana genérica. Se completa con la siguiente llamada:

gnome_dialog_set_parent(GNOME_DIALOG(dialog), GTK_WINDOW(app));

En este punto tiene que decidir si desea hacer un diálogo modal o no modal. En el caso de que quiera un diálogo modal, todo lo que necesita hacer es llamar a la función gnome_dialog_run_and_close y ella lo creará, esperará a que un usuario presione un botón o cierre el diálogo, y entonces cerrará el diálogo. En el caso de que no quiera que el diálogo se cierre cuando algún botón sea pulsado, use la función gnome_dialog_run y después de obtener un resultado, haga lo que necesite para ese botón en particular. Entonces, si desea continuar con el diálogo, vuelva a gnome_dialog_run, y si desea cerrarlo, use gnome_dialog_close. Aquí hay un ejemplo.

GtkWidget *dlg;
GtkWidget *etiqueta;
int i;
...
/*creamos un nuevo diálogo, NO olvide el NULL al final,
  ¡es muy importante!*/
dlg = gnome_dialog_new("Un diálogo",
                       GNOME_STOCK_BUTTON_OK,
                       GNOME_STOCK_BUTTON_APPLY,
                       GNOME_STOCK_BUTTON_CLOSE,
                       NULL);
/* asumimos que app es un puntero a nuestra ventana GnomeApp */
gnome_dialog_set_parent(GNOME_DIALOG(dlg), GTK_WINDOW(app));
...
/*añadimos algún contenido al diálogo aquí*/
etiqueta = gtk_label_new("Algún contenido aleatorio");
gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(dlg)->vbox),etiqueta,
                   FALSE,FALSE,0);
...
/*hacemos un bucle infinito*/
for(;;) {
        i = gnome_dialog_run(GNOME_DIALOG(dlg));
        if(i == 0 || i == 2) {
                /* el usuario presionó OK o close, por eso
                saldremos del bucle y cerraremos el diálogo*/
                gnome_dialog_close(GNOME_DIALOG(dlg));
                break;
        } else if(i < 0) {
       /* el usuario cerró el diálogo desde el gestor
          de ventanas*/
                break;
        } else if(i == 1) {
       /*el usuario presionó aplicar, no queremos que
         se cierre*/
                ...
        }
}

Por defecto el diálogo se destruye cuando es cerrado, por eso no se tiene que preocupar por su destrucción. Puede cambiar esta conducta si lo desea.

Si va a hacer una ventana de diálogo no modal, las cosas se vuelven más complicadas. Cree un diálogo como antes, pero tiene que conectar la señal clicked del widget GnomeDialog. Esta señal tiene como su segundo argumento el número del botón que fue presionado. Después de esto debería usar la función gnome_dialog_set_close para decir a GnomeDialog que queremos cerrar el diálogo cuando el usuario presionó cualquier botón, si quiere este comportamiento. De otro modo deberá llamar a gnome_dialog_close en la función que atiende a la señal clicked, en los botones en los que se debe cerrar el diálogo. Después de esto sólo hay que mostrar el diálogo con gtk_widget_show. A continuación mostramos un ejemplo:

/*la función de tratamiento de clicked*/
static void
dialog_clicked(GnomeDialog *dlg, int boton, gpointer data)
{
        switch(boton) {
        case 1:
    /*el usuario presionó aplicar*/
                ...
                return;
        case 0:
    /*el usuario presionó OK*/
                ...
                  /*seguir hacia abajo para cerrar*/
        case 2:
    /*el usuario presionó cerrar*/
                gnome_dialog_close(dlg);
                break;
        }
}

/*en algún lugar del archivo fuente*/
...
GtkWidget *dlg;
...
/*crear un nuevo diálogo, NO olvide NULL al final, ¡es
  es muy importante!*/
dlg = gnome_dialog_new("Un diálogo",
                       GNOME_STOCK_BUTTON_OK,
                       GNOME_STOCK_BUTTON_APPLY,
                       GNOME_STOCK_BUTTON_CLOSE,
                       NULL);
/* asumimos que app es un puntero a nuestra ventana GnomeApp */
gnome_dialog_set_parent(GNOME_DIALOG(dlg), GTK_WINDOW(app));
...
/*añadimos algún contenido al diálogo aquí*/
...
/*asociamos la función de tratamiento de clicked*/
gtk_signal_connect(GTK_OBJECT(dlg),"clicked",
                   GTK_SIGNAL_FUNC(dialog_clicked),
                   NULL);
/*mostramos el diálogo, note que esto no es un diálogo
  modal, por eso el programa no se bloquea aquí, sigue*/
gtk_widget_show(dlg);

Esto implementa el mismo diálogo que el ejemplo modal anterior, sólo que no modal. Asegúrese de que tiene alguna forma de destruir el diálogo en caso de que no sea necesario, por ejemplo, si un diálogo va a modificar algún objeto, debería ser destruido cuando ese objeto es destruido.

Diálogos de mensaje

GnomeMessageBox es un objeto derivado de GnomeDialog. Se maneja exactamente de la misma manera, la única diferencia es que automáticamente se introduce una etiqueta simple y un icono del tipo del mensaje que contenga el diálogo. Los tipos de diálogos de mensaje son los que siguen:

#define GNOME_MESSAGE_BOX_INFO      "info"
#define GNOME_MESSAGE_BOX_WARNING   "warning"
#define GNOME_MESSAGE_BOX_ERROR     "error"
#define GNOME_MESSAGE_BOX_QUESTION  "question"
#define GNOME_MESSAGE_BOX_GENERIC   "generic"

Para crear un diálogo de mensaje, use la función gnome_message_box_new con el texto del mensaje como primer argumento, el segundo es el tipo de mensaje (uno de los definidos antes), y después cualquier número de botones terminado por un NULL exactamente como en el caso de GnomeDialog. Una vez creado se usa como GnomeDialog.

Diálogos de propiedades

Si tiene que configurar alguna propiedad en su aplicación, tendría que usar el diálogo GnomePropertyBox para realizar esta configuración y así hacer las aplicaciones más consistentes. Nuevamente este objeto se deriva de GnomeDialog, por eso su uso es similar. La diferencia es que GnomePropertyBox define algunas nuevas señales, estas son apply (aplicar) y help (ayuda). Ambas pasan el número de página como segundo argumento, lo que es útil para mostrar la ayuda apropiada en caso de que se solicite. No es así para apply, ya que este sistema se creó para tener un botón de aplicar por cada página y todavía no está acabado, por lo que debería ignorar cualquier señal apply con un número de página distinto de -1, que es el número de aplicación global a todas las páginas. Puede conseguir un apply por cada página introduciendo su propio código, pero no es seguro que este código se llegue a completar. Debería ser más seguro aplicar los cambios globalmente, ya que es lo que está implementado en gnome-libs 1.0.

Para usar diálogos de propiedades, llame a gnome_property_box_new, esto creará un diálogo nuevo con un cuaderno de notas y los siguientes cuatro botones:

OK, que llamará a la función que se encarga de atender la señal 'apply' pasándole todas las páginas una a una y terminando en la página -1, momento en el que cerrará el diálogo.

Aplicar, que efectua la misma operación que el anterior con la salvedad de que no cierra el diálogo.

Cerrar, sólo cerrará el diálogo, y Ayuda que llamará a la función de tratamiento de ayuda si usted ligó alguna.

Después de crear el diálogo debe conectar la señal apply al manejador correspondiente que usted implemente, y recomendamos que conecte también la señal destroy a la ventana apropiada para destruir los datos asociados con el diálogo de propiedades cuando dicha ventana se cierre.

Ahora ya puede crear las diferentes páginas de su diálogo de propiedades, añadiéndolas con gnome_property_box_append_page, este método toma su página como segundo argumento y una etiqueta como tercero (normalmente será simplemente un GtkLabel). Tiene también que conectar las diferentes señales a los widgets de sus páginas para que al editar alguno de ellos, el diálogo de propiedades aparezca como cambiado (de otra forma los botones Aplicar y OK no serán sensibles). Esto se hace llamando a gnome_property_box_changed cada vez que el usuario cambia algo en los widgets. Por ejemplo en el widget de entrada (y derivados) se conecta la señal changed. Siga este ejemplo:

/*rutina de tratamiento de aplicar*/
static void
property_apply(GnomePropertyBox *caja, int pag_num, gpointer data)
{
        /*ignora los números de página distintos de -1*/
        if(pag_num!=-1)
                return;
        /*hacer la rutina de aplicar aquí*/
        ...
}
...
/*en algún lugar del archivo fuente*/
GtkWidget *pcaja;
GtkWidget *widget;
...
pcaja = gnome_property_box_new();
gtk_signal_connect(GTK_OBJECT(pcaja),"apply",
        GTK_SIGNAL_FUNC(property_apply),NULL);
...
/*se crea una página para la caja de propiedades y se añade
  al contenedor llamado widget*/
gnome_property_box_append_page(GNOME_PROPERTY_BOX(pcaja),
          widget, gtk_label_new("UnaPágina"));
/*ahora se añaden otras páginas de una manera similar*/
...
/*mostramos la caja de diálogo*/
gtk_widget_show_all(pcaja);

Diálogo de Selección de Archivos

GNOME no tiene su propio diálogo de selección de archivos, aunque está planeado crearlo en un futuro, por ahora tiene que usar el típico diálogo de GTK+.

El uso del diálogo de selección de archivos es muy simple. Cree el diálogo con gtk_file_selection_new, pasando el título del diálogo como argumento. Después de esto conecte la señal clicked a los botones OK y Cancelar. Por ejemplo para un diálogo de "abrir archivo", puede probar que el archivo es del tipo correcto cuando el usuario presiona OK y si todo va bien cierre el diálogo (normalmente con gtk_widget_destroy), o bien para el diálogo de guardar archivo, puede preguntar si el archivo existe. Normalmente es más seguro y sencillo hacer el diálogo de selección de archivos no modal. Asi se asegura de que destruirá el diálogo de selección de archivo cuando el objeto o ventana vaya a trabajar con él. Aquí está la función que invoca al diálogo de "guardar como" para Achtung, un programa de presentaciones en el que estamos trabajando.

void
presentation_save_as (AchtungPresentation *p)
{
        GtkFileSelection *fsel;
 
        g_return_if_fail (p != NULL);
        g_return_if_fail (p->doc != NULL);
 
        fsel = (GtkFileSelection *)
        gtk_file_selection_new (_("Guardar presentación como..."));
        if (p->real_file && p->filename)
                gtk_file_selection_set_filename (fsel, p->filename);
 
        gtk_object_set_data(GTK_OBJECT(fsel),"p",p);
 
        /* Conectamos las señales con OK y Cancelar */
        gtk_signal_connect (GTK_OBJECT (fsel->ok_button), "clicked",
                            GTK_SIGNAL_FUNC (save_ok), fsel);
        gtk_signal_connect_object (GTK_OBJECT (fsel->cancel_button), 
                                   "clicked",
                                   GTK_SIGNAL_FUNC (gtk_widget_destroy), 
                                   GTK_OBJECT(fsel));

        gtk_window_position (GTK_WINDOW (fsel), GTK_WIN_POS_MOUSE);

        /*si la presentación muere también lo harán los diálogos*/
        gtk_signal_connect_object_while_alive(GTK_OBJECT (p), "destroy",
                                   GTK_SIGNAL_FUNC (gtk_widget_destroy), 
                                   GTK_OBJECT(fsel));

        gtk_widget_show (GTK_WIDGET (fsel));
}

Actualmente, esta función es un método "Guardar como" de la clase AchtungPresentation, utilizando lenguaje de orientación a objetos. AchtungPresentation es un GTKObject que usamos para guardar todos los datos de la presentación (este es un ejemplo bonito de cómo usar GtkObject para cosas no relacionadas directamente con los widgets o la programación de GUI's). Primero se revisan los argumentos de la función con g_return_if_fail, esto se hace sólo por motivos de depuración. Después creamos un nuevo GtkFileSelection con el título "Guardar presentación como...". Ignore la macro _() alrededor de las cadenas por el momento, se usa para la internacionalización. Después de todo esto se verifica si la presentación ya tiene un nombre de archivo asociado, y si es así, se pone este nombre en el diálogo de selección de archivo. Entonces conectamos el botón OK con la función save_ok definida en algún lugar del archivo y pasamos el diálogo como argumento. Entonces usamos connect_object para unir el botón Cancel con la destrucción del diálogo de selección. El método connect_object es similar a connect pero cuando llama a la función pasará el objeto del campo de datos como primer argumento de la función. Por eso al conectarlo con gtk_widget_destroy destruirá el objeto pasado en el campo de datos, que es el diálogo de selección de archivos. Entonces situamos el diálogo cerca del ratón. En un futuro, cuando este diálogo se derive de GnomeDialog, no necesitará hacerlo, porque se hará de acuerdo con el resto de los diálogos de GNOME. Todavía usamos otro método conectado a una señal... Esta vez gtk_signal_connect_object_while_alive, el cual es similar a connect_object, pero tiene un preciosa peculiaridad. La señal se desconectará cuando el objeto pasado en el campo de datos muera. Necesitamos que ocurra porque el diálogo de selección de archivos con toda probabilidad será destruido antes de que la presentación misma sea destruida, podría intentar destruir un diálogo de selección de archivos que en realidad no existe y con probabilidad causará una violación de segmento, colgándose. Este camino es seguro y si el diálogo de selección de archivo está cuando la presentación es destruida, es destruida con él.

Diálogo Acerca de...

Probablemente quiera tener una opción "Acerca de..." en el menú "Ayuda" de su aplicación, y debería mostrarse en un diálogo estándar. Hay un diálogo en GNOME para este tipo de propósitos, la clase GnomeAbout. Se crea con gnome_about_new, que tiene el siguiente prototipo

GtkWidget* gnome_about_new(const gchar *title, /* Nombre de la aplicación. */
                           const gchar *version, /* Versión. */
                           const gchar *copyright, /* Copyright(una línea.) */
                           const gchar **authors, /* Lista con los autores
                           terminada con NULL. */
                           const gchar *comments, /* Otros comentarios. */
                           const gchar *logo /* Un archivo pixmap
                           con el logo. */
                           );

Después de crear la caja de diálogo, debería establecer la ventana de la aplicación como su padre con gnome_dialog_set_parent. Y entonces puede mostrar el diálogo. Lo siguiente implementa un diálogo "acerca de", asumimos que VERSION ha sido definida con #define para ser una cadena con el número de la versión. También pasamos como logotipo un NULL, indicando que no tenemos una imagen que mostrar.

GtkWidget* dlg;
char *authors[] = {
        "George Lebl",
        NULL;
};

dlg = gnome_about_new("Alguna aplicación", /* Nombre de la aplicación. */
                      VERSION, /* Versión. */
                      "(c) 1999 George Lebl", /* Copyright (una línea.) */
                      authors, /* Lista con los autores, terminado con NULL*/
                      "bla bla bla", /* Otros comentarios. */
                      NULL /* Un archivo pixmap con el logo. */
                      );

gnome_dialog_set_parent(GNOME_DIALOG(dlg), GTK_WINDOW(app));

gtk_widget_show(dlg);

Entradas

Algunas veces, especialmente en los diálogos de propiedades, querrá añadir campos para introducir texto, archivos, pixmaps, iconos o reales de doble precisión (N.T: double). Esto es lo que hace los widgets gnome-*entry.

GnomeEntry

Es una entrada para texto regular, pero incluye historia de los valores introducidos anteriormente. Note que este widget no está derivado de GtkEntry, sino que contiene a un objeto de esta clase. Todo esto significa que no puede usar los métodos de GtkEntry sobre este objeto directamente, tiene que obtener un puntero al objeto GtkEntry que hay dentro de GnomeEntry. Cuando llama a gnome_entry_new, se le pasa una cadena history_id, es un identificador único para identificar a esta entrada o a este tipo de entradas en su aplicación. Todas las entradas que comparten history_id tendrán una historia común. Después de que cree un GnomeEntry tendrá que usar la función gnome_entry_gtk_entry para obtener el puntero al objeto GtkEntry y asociarle alguna señal o manipular el texto. Aquí hay un ejemplo:

GtkWidget *gnomeentry;
GtkWidget *gtkentry;
...
gnomeentry = gnome_entry_new("texto1");

/* tomamos GtkEntry para enlazarlo con la señal "changed" y conocer
   cuándo el usuario ha cambiado la entrada */
gtkentry = gnome_entry_gtk_entry(GNOME_ENTRY(gnomeentry));
gtk_signal_connect(GTK_OBJECT(gtkentry),"changed",
                   GTK_SIGNAL_FUNC(entry_changed), NULL);

GnomeFileEntry

GnomeEntry es la base para GnomeFileEntry. De nuevo no está derivado, sino que una instancia de GnomeEntry, está contenida en GnomeFileEntry. Este tipo de jerarquía está presente en todos los widget de entrada de GNOME. GnomeFileEntry añade un botón de búsqueda en la parte derecha de la entrada, acepta también archivos que provengan del gestor de archivos por medio del mecanismo de "arrastrar y soltar", por ejemplo. Su uso es sumamente similar a GnomeEntry. Se crea la entrada con gnome_file_entry_new. El primer argumento es el history_id del GnomeEntry, y el segundo argumento es el título de la caja de diálogo del buscador. Para conseguir el GtkEntry, de nuevo use el método gtk_entry, llamado gnome_file_entry_gtk_entry. Para obtener finalmente el nombre del archivo, puede leer el texto de la misma forma que GtkEntry, o podría usar otros métodos, gnome_file_entry_get_full_path , el cual toma una bandera file_must_exist como segundo argumento. Si éste está activado (TRUE), la función devuelve NULL cuando no existe el archivo. Si es FALSE o el archivo existe, la función devuelve el camino entero hasta el archivo.

GnomePixmapEntry

Esto es una entrada para introducir imágenes cualquier tipo. Vuelve a incluir (no se deriva de) GnomeFileEntry, por eso puede hacer todo lo que GnomeFileEntry puede hacer (incluso aceptar los archivos arrastrados desde el gestor de archivos). De todas formas esta entrada añade un cuadro de previsualización para la imagen que se encuentra en la entrada. También su diálogo de selección de archivo incluye un cuadro de previsualización en el lado derecho del listado de archivos.

Su uso es muy similar a las entradas anteriores. Se llama a gnome_pixmap_entry_new con los mismos argumentos que GnomeFileEntry, con una bandera añadida, do_preview. Esta bandera especifica si la caja de previsualización es visible o no. Pero tenga cuidado, esto no ahorra memoria, sólo ahorra espacio. Use de nuevo gnome_pixmap_entry_gtk_entry para obtener el widget GtkEntry. Para leer el nombre del archivo de la imagen, si pudo ser cargada como una imagen en el previsualizado (usando Imlib), puede usar gnome_pixmap_entry_get_filename, que devuelve NULL si el archivo de la imagen no existe o no pudo ser cargada, y el nombre completo del archivo en el caso contrario.

GnomeIconEntry

La entrada de iconos es muy similar a GnomePixmapEntry, pero está pensado para imágenes con el tamaño estándar de los iconos de 48x48. También al margen de la caja de previsualización hay un botón con la imagen escalada a 48x48. Si presiona el botón, obtendrá una lista de imágenes del mismo directorio en el que está el icono actual. Para crear una entrada de icono use gnome_icon_entry_new con history_id y browse_dialog_title como argumentos tipo cadena. Una vez que tiene un icono existente con una una imagen real, use gnome_icon_entry_get_filename que funciona como gnome_pixmap_entry_get_filename. También puede conseguir GtkEntry usando gnome_icon_entry_gtk_entry