Existen diferentes widgets en GTK+ que pueden ser ajustados visualmente por el usuario mediante el ratón o el teclado. Un ejemplo son los widgets de selección descritos en la sección Widgets de selección de rango. También hay otros widgets que pueden ser ajustados parcialmente, por ejemplo el widget de texto o el viewport.
Como es lógico el programa tiene que poder reaccionar a los cambios que el usuario realiza. Mediante señales especiales se podría conseguir saber qué y cúanto ha sido ajustado, pero en el caso de que se quiera conectar la señal con diferentes widgets, de manera que todos cambien al mismo tiempo, el proceso puede ser un poco tedioso.
El ejemplo más obvio es conectar una barra de desplazamiento a una región con texto. Si cada widget posee su propia forma de establecer u obtener sus valores de ajuste el programador puede que tenga que escribir sus propios controladores de señales para traducir el resultado de la señal producida por un widget como el argumento de una función usada para determinar valores en otro widget.
Para resolver este problema GTK+ usa objetos del tipo GtkAdjustment. Con ellos se consigue almacenar y traspasar información de una forma abstracta y flexible. El uso más obvio es el de almacenes de párametros para widgets de escala (barras deslizantes y escalas). Como los GtkAdjustment derivan de GtkObject poseen cualidades intrínsecas que les permiten ser algo más que simples estructuras de datos. Lo más importante es que pueden emitir señales que a su vez pueden ser usadas tanto para reaccionar frente al cambio de datos introducidos por el usuario como para transferir los nuevos valores de forma transparente entre widgets ajustables.
Los ajustes se pueden crear usando:
GtkObject *gtk_adjustment_new( gfloat value,
gfloat lower,
gfloat upper,
gfloat step_increment,
gfloat page_increment,
gfloat page_size );
El argumento value
es el valor inicial que le queremos dar
al ajuste. Normalmente se corresponde con las posiciones situadas
más arriba y a la izquierda de un widget ajustable. El argumento
lower
especifica los valores más pequeños que el ajuste
puede contener. A su vez con step_increment
se especifica el
valor más pequeño en el que se puede variar la magnitud en
cuestión (valor de paso asociado), mientras que page_increment
es el mayor. Con page_size
se determina el valor visible de un
widget.
Los widgets ajustábles se pueden dividir en dos categorias
diferentes, aquellos que necesitan saber las unidades de la cantidad
almacenada y los que no. Este último grupo incluye los widgets
de tamaño (barras deslizantes, escalas, barras de estado, o botones
giratorios). Normalmente estos widgets son ajustados
``directamente'' por el usuario. Los argumentos lower
y
upper
serán los limites dentro de los cuales el usuario puede
manipular los ajustes. Por defecto sólo se modificará el
value
(valor) de un ajuste.
El otro grupo incluye los widgets de texto, la lista compuesta o
la ventana con barra deslizante. Estos widgets usan valores en
pixels para sus ajustes, y normalmente son ajustados
``indirectamente'' mediante barras deslizantes. Aunque todos los
widgets pueden crear sus propios ajustes o usar otros creados por
el programador con el segundo grupo suele ser conveniente dejarles que
creen sus propios ajustes. Normalmente no tendrán en cuenta ninguno
de los valores de un ajuste proporcionado por el programador, excepto
value
, pero los resultados son, en general, indefinidos
(entiendase que tendrá que leer el código fuente para saber que
pasa con cada widget).
Probablemente ya se habrá dado cuenta de que como los widgets
de texto (y todos los widgets del segundo grupo), insisten en
establecer todos los valores excepto value
, mientras que las
barras deslizantes sólo modifican value
, si se comparte un
objeto de ajuste entre una barra deslizante y un widget de texto
al manipular la barra se modificará el widget de texto. Ahora
queda completamente demostrada la utilidad de los ajustes. Veamos un
ejemplo:
/* creamos un ajuste */
text = gtk_text_new (NULL, NULL);
/* lo usamos con la barra deslizante */
vscrollbar = gtk_vscrollbar_new (GTK_TEXT(text)->vadj);
Puede que se esté preguntando cómo es posible crear sus propios controladores para responder a las modificaciones producidas por el usuario y cómo obtener el valor del ajuste hecho por este. Para aclarar esto y otras cosas vamos a estudiar la estructura del ajuste
struct _GtkAdjustment
{
GtkData data;
gfloat lower;
gfloat upper;
gfloat value;
gfloat step_increment;
gfloat page_increment;
gfloat page_size;
};
Lo primero que hay que aclarar es que no hay ninguna macro o función
de acceso que permita obtener el value
de un GtkAdjustment, por
lo que tendrá que hacerlo usted mismo. Tampoco se preocupe mucho
porque la macro GTK_ADJUSTMENT (Object)
comprueba los tipos
durante el proceso de ejecución (como hacen todas las macros de GTK+
que sirven para comprobar los tipos).
Cuando se establece el value
de un ajuste normalmente se quiere
que cualquier widget se entere del cambio producido. Para ello
GTK+ posee una función especial:
void gtk_adjustment_set_value( GtkAdjustment *adjustment,
gfloat value );
Tal y como se mencionó antes GtkAdjustment es una subclase de GtkObject
y por tanto puede emitir señales. Así se consigue que se actualicen
los valores de los ajustes cuando se comparten entre varios widgets.
Por tanto todos los widgets ajustables deben conectar controladores
de señales a sus señales del tipo value_changed
. Esta es la
definición de la señal como viene en struct _GtkAdjustmentClass
void (* value_changed) (GtkAdjustment *adjustment);
Todos los widgets que usan GtkAdjustment deben emitir esta señal cuando cambie el valor de algún ajuste. Esto sucede cuando el usuario cambia algo o el programa modifica los ajustes mediante. Por ejemplo si queremos que rote una figura cuando modificamos un widget de escala habría que usar una respuesta como esta:
void cb_rotate_picture (GtkAdjustment *adj, GtkWidget *picture)
{
set_picture_rotation (picture, adj->value);
...
y conectarla con el ajuste del widget de escala mediante:
gtk_signal_connect (GTK_OBJECT (adj), "value_changed",
GTK_SIGNAL_FUNC (cb_rotate_picture), picture);
¿Qué pasa cuando un widget reconfigura los valores
upper
o lower
(por ejemplo cuando se añade más texto)?
Simplemente que se emite la señal changed
, que debe ser
parecida a:
void (* changed) (GtkAdjustment *adjustment);
Los widgets de tamaño normalmente conectan un controlador a
esta señal, que cambia el aspecto de éste para reflejar el
cambio. Por ejemplo el tamaño de la guía en una barra deslizante
que se alarga o encoge según la inversa de la diferencia de los
valores lower
y upper
.
Probablemente nunca tenga que conectar un controlador a esta señal a no ser que esté escribiendo un nuevo tipo de widget. Pero si cambia directamente alguno de los valores de GtkAdjustment debe hacer que se emita la siguiente señal para reconfigurar todos aquellos widgets que usen ese ajuste:
gtk_signal_emit_by_name (GTK_OBJECT (adjustment), "changed");