El widget texto permite mostrar y editar multiples líneas de texto. Admite texto en varios colores y con varios tipos de letra, permitiendo mezclarlos de cualquier forma que desee. También hay un gran número de teclas para la edición de textos, que son compatibles con Emacs.
El widget texto admite copiar-y-pegar, incluyendo la utilización de doble y triple-click para seleccionar una palabra y una línea completa, respectivamente.
Sólo hay una función para crear un nuevo widget texto.
GtkWidget *gtk_text_new( GtkAdjustment *hadj,
GtkAdjustment *vadj );
Los argumentos nos permitirán dar al widget texto punteros a
GtkAdjustement
que pueden ser utilizados para controlar la visión
de la posición del widget. Si le ponemos un valor NULL en
cualquiera de los dos argumentos (o en los dos), la función
gtk_text_new
creará su propio ajuste.
void gtk_text_set_adjustments( GtkText *text,
GtkAdjustment *hadj,
GtkAdjustment *vadj );
La función de arriba permite cambiar en cualquier momento el ajuste horizontal y vertical de un widget texto.
El widget texto no crea automáticamente sus propiar barras de desplazamiento cuando el texto a mostrar es demasiado largo para la ventana en la que se encuentra. Tenemos que crearlas y añadirlas a la capa del display nosotros mismos.
vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
gtk_box_pack_start(GTK_BOX(hbox), vscrollbar, FALSE, FALSE, 0);
gtk_widget_show (vscrollbar);
El trozo de código de arriba crea una nueva barra de desplazamiento
vertical, y la conecta con el ajuste vertical del widget
de texto, text
. Entonces la empaqueta en un cuadro de la forma
usual.
Observe que, actualmente el widget GtkText no admite barras de desplazamiento horizontal.
Principalmente hay dos maneras de utilizar un widget de texto: permitiendo al usuario editar el texto, o permitiéndonos mostrar varias líneas de texto al usuario. Para cambiar entre estos dos modos de operación, el widget de texto tiene las siguientes funciones:
void gtk_text_set_editable( GtkText *text,
gint editable );
El argumento editable
es un valor TRUE o FALSE que especifica si se
permite al usuario editar los contenidos del widget texto.
Cuando el widget texto se pueda editar, mostrará un cursor
en la posición actual de inserción.
Sin embargo la utilización del widget en estos dos modos no es algo permanente, ya que puede cambiar el estado editable del widget texto e insertar texto en cualquier momento.
El widget texto corta las líneas de texto que son demasiado largas para que quepan en una sólo línea en la ventana. Su comportamiento por defecto es cortar las palabras donde se terminan las líneas. Esto puede cambiarse utilizando la siguiente función:
void gtk_text_set_word_wrap( GtkText *text,
gint word_wrap );
Utilizando esta función podremos especificar que el widget
texto debería cortar las líneas largas en los límites de las
palabras. El argumento word_wrap
es un valor TRUE o FALSE.
El punto actual de inserción en un widget texto puede cambiarse utilizando
void gtk_text_set_point( GtkText *text,
guint index );
donde index
es la posición en la que poner el punto de inserción.
Análogamente tenemos la función para obtener la posición del punto de inserción:
guint gtk_text_get_point( GtkText *text );
Una función que es útil en combinación con las dos anteriores es
guint gtk_text_get_length( GtkText *text );
que devuelve la longitud actual del widget texto. La longitud es el número de caracteres que hay en el bloque de texto, incluyendo caracteres como el retorno de carro, que marca el final de las líneas.
Para insertar texto en la posición actual del cursor, tendrá que
utilizar la función gtk_text_insert
, que nos permitirá
especificar los colores de fondo y de la letra y un tipo de letra para
el texto.
void gtk_text_insert( GtkText *text,
GdkFont *font,
GdkColor *fore,
GdkColor *back,
const char *chars,
gint length );
Pasar un valor NULL
como el color de la letra (fore
), el
color de fondo (back
) o el tipo de letra (font
) hará que
se utilicen los valores que indiquen el estilo del widget.
Utilizar un valor de -1
para el parámetro length
hará
que se inserte todo el texto.
El widget texto es uno de los pocos de GTK que se redibuja
a sí mismo dinámicamente, fuera de la función gtk_main
. Esto
significa que todos los cambios en el contenido del widget texto
se manifestarán inmediatamente. Para permitirnos realizar varias
actualizaciones del widget de texto sin que se redibuje
continuamente, podemos congelar el widget, lo que hará que pare
momentaneamente de redibujarse a sí mismo cada vez que haya algún
cambio. Podemos descongelarlo cuando hayamos acabado con nuestras
actualizaciones.
Las siguientes dos funciones realizarán la acción de congelar y descongelar el widget:
void gtk_text_freeze( GtkText *text );
void gtk_text_thaw( GtkText *text );
Se puede borrar el texto que se encuentra en el punto actual de inserción del widget de texto mediante dos funciones. El valor devuelto es TRUE o FALSE en función del éxito de la operación.
gint gtk_text_backward_delete( GtkText *text,
guint nchars );
gint gtk_text_forward_delete ( GtkText *text,
guint nchars );
Si quiere recuperar el contenido del widget de texto, entonces
la macro GTK_TEXT_INDEX(t, index)
le permitirá obtener el
carácter que se encuentra en la posición index
del widget
de texto t
.
Para obtener mayores bloques de texto, podemos utilizar la función
gchar *gtk_editable_get_chars( GtkEditable *editable,
gint start_pos,
gint end_pos );
Esta es una función de la clase padre del widget texto. Un valor
de -1 en end_pos
significa el final del texto. El índice del
texto empieza en 0.
La función reserva un espacio de memoria para el bloque de texto,
por lo que no debe olvidarse de liberarlo con una llamada a
g_free
cuando haya acabado el bloque.
El widget texto tiene ciertos atajos de teclado preinstalados para las funciones de edición estándar, movimiento y selección. Pueden utilizarse mediante combinaciones de las teclas Control y Alt.
Además, si se mantiene apretada la tecla de Control y se utilizan las teclas de movimiento, el cursor se moverá por palabras en lugar de por caracteres. Manteniendo apretada la tecla Shift, las teclas de movimiento harán que se extienda la selección.
/* principio del ejemplo text text.c */
/* text.c */
#include <stdio.h>
#include <gtk/gtk.h>
void text_toggle_editable (GtkWidget *checkbutton,
GtkWidget *text)
{
gtk_text_set_editable(GTK_TEXT(text),
GTK_TOGGLE_BUTTON(checkbutton)->active);
}
void text_toggle_word_wrap (GtkWidget *checkbutton,
GtkWidget *text)
{
gtk_text_set_word_wrap(GTK_TEXT(text),
GTK_TOGGLE_BUTTON(checkbutton)->active);
}
void close_application( GtkWidget *widget, gpointer data )
{
gtk_main_quit();
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *box1;
GtkWidget *box2;
GtkWidget *hbox;
GtkWidget *button;
GtkWidget *check;
GtkWidget *separator;
GtkWidget *table;
GtkWidget *vscrollbar;
GtkWidget *text;
GdkColormap *cmap;
GdkColor colour;
GdkFont *fixed_font;
FILE *infile;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_usize (window, 600, 500);
gtk_window_set_policy (GTK_WINDOW(window), TRUE, TRUE, FALSE);
gtk_signal_connect (GTK_OBJECT (window), "destroy",
GTK_SIGNAL_FUNC(close_application),
NULL);
gtk_window_set_title (GTK_WINDOW (window), "Text Widget Example");
gtk_container_border_width (GTK_CONTAINER (window), 0);
box1 = gtk_vbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box1);
gtk_widget_show (box1);
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
gtk_widget_show (box2);
table = gtk_table_new (2, 2, FALSE);
gtk_table_set_row_spacing (GTK_TABLE (table), 0, 2);
gtk_table_set_col_spacing (GTK_TABLE (table), 0, 2);
gtk_box_pack_start (GTK_BOX (box2), table, TRUE, TRUE, 0);
gtk_widget_show (table);
/* Crear el widget GtkText */
text = gtk_text_new (NULL, NULL);
gtk_text_set_editable (GTK_TEXT (text), TRUE);
gtk_table_attach (GTK_TABLE (table), text, 0, 1, 0, 1,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (text);
/* Añadir una barra de desplazamiento vertical al widget GtkText */
vscrollbar = gtk_vscrollbar_new (GTK_TEXT (text)->vadj);
gtk_table_attach (GTK_TABLE (table), vscrollbar, 1, 2, 0, 1,
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
gtk_widget_show (vscrollbar);
/* Obtener el mapa de colores del sistema y conseguir el color rojo */
cmap = gdk_colormap_get_system();
colour.red = 0xffff;
colour.green = 0;
colour.blue = 0;
if (!gdk_color_alloc(cmap, &colour)) {
g_error("couldn't allocate colour");
}
/* Cargar un fuente de tamaño fijo */
fixed_font = gdk_font_load ("-misc-fixed-medium-r-*-*-*-140-*-*-*-*-*-*");
/* Al enviar la señal relize a un widget se crea una ventana para el
* mismo, y nos permite insertar texto */
gtk_widget_realize (text);
/* Congela el widget text, lo que nos permite hacer varias
* actualizaciones */
gtk_text_freeze (GTK_TEXT (text));
/* Insertamos algún texto coloreado */
gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
"Supports ", -1);
gtk_text_insert (GTK_TEXT (text), NULL, &colour, NULL,
"colored ", -1);
gtk_text_insert (GTK_TEXT (text), NULL, &text->style->black, NULL,
"text and different ", -1);
gtk_text_insert (GTK_TEXT (text), fixed_font, &text->style->black, NULL,
"fonts\n\n", -1);
/* Cargamos el fichero text.c en la ventana de texto */
infile = fopen("text.c", "r");
if (infile) {
char buffer[1024];
int nchars;
while (1)
{
nchars = fread(buffer, 1, 1024, infile);
gtk_text_insert (GTK_TEXT (text), fixed_font, NULL,
NULL, buffer, nchars);
if (nchars < 1024)
break;
}
fclose (infile);
}
/* Descongelamos el widget text, permitiéndonos ver todos los
* cambios */
gtk_text_thaw (GTK_TEXT (text));
hbox = gtk_hbutton_box_new ();
gtk_box_pack_start (GTK_BOX (box2), hbox, FALSE, FALSE, 0);
gtk_widget_show (hbox);
check = gtk_check_button_new_with_label("Editable");
gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, FALSE, 0);
gtk_signal_connect (GTK_OBJECT(check), "toggled",
GTK_SIGNAL_FUNC(text_toggle_editable), text);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), TRUE);
gtk_widget_show (check);
check = gtk_check_button_new_with_label("Wrap Words");
gtk_box_pack_start (GTK_BOX (hbox), check, FALSE, TRUE, 0);
gtk_signal_connect (GTK_OBJECT(check), "toggled",
GTK_SIGNAL_FUNC(text_toggle_word_wrap), text);
gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(check), FALSE);
gtk_widget_show (check);
separator = gtk_hseparator_new ();
gtk_box_pack_start (GTK_BOX (box1), separator, FALSE, TRUE, 0);
gtk_widget_show (separator);
box2 = gtk_vbox_new (FALSE, 10);
gtk_container_border_width (GTK_CONTAINER (box2), 10);
gtk_box_pack_start (GTK_BOX (box1), box2, FALSE, TRUE, 0);
gtk_widget_show (box2);
button = gtk_button_new_with_label ("close");
gtk_signal_connect (GTK_OBJECT (button), "clicked",
GTK_SIGNAL_FUNC(close_application),
NULL);
gtk_box_pack_start (GTK_BOX (box2), button, TRUE, TRUE, 0);
GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
gtk_widget_grab_default (button);
gtk_widget_show (button);
gtk_widget_show (window);
gtk_main ();
return 0;
}
/* fin del ejemplo */