Jinete 0.4 A GUI library. By David A. Capello, 2005.
#include <std_disclaimer.h>
"No me responsabilizo de ningún efecto, adverso u otro que este código pueda tener sobre usted, su ordenador, su salud, su perro, o cualquier otra cosa que pueda imaginar. Uselo bajo su propia responsabilidad."
Jinete es una librería que proporciona un Interfaz Gráfico de Usuario (GUI por sus siglas en inglés), sencilla y rápida tanto de usar, como de programar y diseñar diálogos. Conjuntamente con la librería Allegro, se encarga de controlar los eventos que produce el usuario a través del ratón (mouse) y el teclado.
Jinete es gift-ware (software-regalo). Puede usar, modificar, redistribuir, y generalmente modificarlo de cualquier forma que desee, y no debe darme nada a cambio. Si redistribuye partes de este código o hace una aplicación con él, sería bonito que mencionase Jinete en alguna parte de los créditos, pero no está obligado a hacerlo.
El GUI se maneja a través de widgets (controles u objetos gráficos). Cada widget puede contener varios widgets hijos, donde cada uno de éstos tiene un puntero a su único padre; siendo el padre raíz de todos los widgets: el manager (gestor) principal del GUI (el cual también es un widget).
Jinete es controlado con el manager principal, el cual es creado por primera y única vez a través de la primer llamada de jmanager_new, y deberá ser eliminado mediante jmanager_free.
Los managers sólo pueden contener ventanas dentro, mientras que las ventanas pueden contener todo tipo de widgets, inclusive otros managers alternativos (o sub-managers) los cuales a su vez pueden contener otras ventanas (con Jinete puede lograr algo así como la MDI de Windows).
El manager principal controla los mensajes y los despacha a los demás widgets. Cabe destacar que todo mensaje enviado a través de jmanager_send_message no es procesado de inmediato, dicho mensaje solo se guardará en una cola para luego ser despachado (si espera una respuesta inmediata, vea jmanager_dispatch_messages o jwidget_send_message).
Vea también: jmanager_new, ji_manager_free, jmanager_send_message, ji_manager_dispatch_messages.
struct_type *mem1 = malloc (sizeof (struct_type) * n_structs).
Los widgets son los componentes, objetos o controles del interfaz gráfico; un botón, o una ventana son ejemplos de widgets. En Jinete, el tipo JWidget representa dicho controles:
Es decir que JWidget en realidad se trata de un puntero a una estructura jwidget definida en el archivo "jinete/widget.h".typedef struct jwidget *JWidget;
En general, la gran mayoría de los tipos en Jinete (definidos en "jinete/base.h") se tratan de punteros a estructuras definidas en cada uno de los archivos de cabecera particulares.
Para modificar el comportamiento de un widget, se deben agregar ganchos ("hooks", JHook en Jinete), los cuales se encargan de interceptar mensajes.
Los campos de la estructura jwidget son:
Es el valor que se le pasa a la función jwidget_new (puede tratarse de un valor devuelto por ji_register_widget_type).
Retornará valores continuos a JI_USER_WIDGET.
Vea también: jwidget_free.
Los widgets hijos también son eliminados (recursivamente). El campo "widget->specific_data" también es eliminado (mediante jfree).
Envía el mensaje JM_DESTROY al widget inmediatamente.
Vea también: jwidget_new, _ji_free_all_widgets, Manager, JM_DESTROY.
El "msg_proc" es un puntero a una función encargada de recibir cada mensaje y procesarlo. Esta función debe retornar FALSE si no utiliza un determinado mensaje y/o quiere dejarle el paso a un posible "msg_proc" padre que se encuentre en el widget.
Vea también: ji_register_widget_type, jwidget_get_hook, jwidget_get_data.
Vea también: ji_register_widget_type.
Vea también: jwidget_set_name, ji_load_widget, Archivos JID.
No utilice el puntero si es que lo consiguió antes de una llamada a jwidget_set_text. EVITE SIEMPRE hacer esto:
const char *text = jwidget_get_text (widget); jwidget_set_text (widget, "Hola"); printf (text);
Vea también: jwidget_set_text.
Vea también: jwidget_set_align.
Vea también: jwidget_find_name.
Vea también: jwidget_get_text, jwidget_dirty.
Vea también: jwidget_get_align.
Vea también: jwidget_is_magnetic, jmanager_attract_focus.
Vea también: jwidget_is_expansive, jbox_new.
Vea también: jwidget_is_decorative, Window (ventana), Theme (tema).
Vea también: jwidget_magnetic, jwidget_expansive, jwidget_decorative, jwidget_autodestroy.
Vea también: jwidget_focusrest.
Si desea redibujar un widget de forma instantánea:
Tenga en cuenta, que muchas funciones que cambian el estado del widget, suelen llamar a jwidget_dirty para redibujar el widget con su nuevo estado.jwidget_dirty (widget); jwidget_flush_redraw (widget); jmanager_dispatch_draw_messages ();
Vea también: jmanager_poll, JI_SIGNAL_DIRTY.
Emite la señal JI_SIGNAL_NEW_PARENT para "child", y JI_SIGNAL_ADD_CHILD para "widget".
Vea también: jwidget_remove_child, jwidget_replace_child, JI_SIGNAL_NEW_PARENT, JI_SIGNAL_ADD_CHILD.
Vea también: jwidget_add_child.
Vea también: jwidget_add_child, jwidget_replace_child.
Vea también: jwidget_add_child, jwidget_remove_child.
Vea también: jwidget_get_parents.
Vea también: jwindow_get_manager.
Deberá liberar la lista devuelta mediante jlist_free.
Vea también: jwidget_get_parent, jlist_free.
Deberá liberar la lista devuelta mediante jlist_free.
Devolverá el widget más lejano de "widget" (el hijo más profundo) si es que éste se abarca el punto (x, y).
El rectángulo devuelto JRect deberá ser liberado mediante jrect_free.
Vea también: jwidget_get_region, jrect_free.
Deberá liberar la región devuelta mediante jregion_free.
Vea también: jwidget_get_position, jwidget_get_drawable_region, jregion_free.
Deberá liberar la región devuelta mediante jregion_free.
Vea también: jwidget_get_region, jregion_free.
int length = ji_font_text_len (widget->text_font, widget->text); int height = text_height (widget->text_font);
Vea también: ji_font_text_len.
Vea también: jwidget_set_name, Archivos JID.
Valores posibles para las banderas widget->flags. Evite usar estos valores directamente, en su lugar intente usar las funciones "jwidget_is_..." donde sea posible.
Vea también: jwidget_decorative, jwidget_autodestroy, jwidget_hard_capture_mouse.
Cuando se genera un mensaje, al ser despachado se comienza enviando el mismo a los ganchos de los widgets receptores, comenzando del primer gancho (el cual sería el último gancho agregado) hasta el último gancho del widget.
Recuerde que si intercepta un mensaje, debe retornar TRUE indicando que el mensaje fue utilizado, así frena el enviado de mensajes a otros ganchos. Esto es válido para todos los mensajes menos para JM_DESTROY. Ya que devolviendo TRUE, los ganchos próximos no recibirán dicho mensaje y es posible que algo de memoria no se libere.
Es enviado a todos los widgets de una ventana cuando está es abierta en un determinado manager.
Vea también: JM_CLOSE.
Cuando una ventana es cerrada, este mensaje se envía a todos los widgets de la misma.
Vea también: JM_OPEN, JM_DESTROY.
Se envía al eliminar el widget mediante jwidget_free. Un widget recibe una única vez este mensaje (siendo además el último mensaje que recibirá). Recuerde retornar FALSE para no frenar el envío del mensaje a los ganchos próximos.
Vea también: JM_CLOSE.
Mensaje utilizado para obtener el tamaño necesario para el widget. Debe rellenar las variables msg->reqsize.w y msg->reqsize.h, y retornar TRUE si así lo hizo.
Vea también: jwidget_request_size.
Mensaje utilizado para cambiar el tamaño del widget, si lo intercepta, deberá hacer un "jrect_copy (widget->pos, &msg->setpos.rect)".
Enganchar este mensaje es útil solamente si piensa reacomodar los hijos cada vez que cambie la posición del widget (es decir, siempre que un widget acepte hijos, deberá hacer su propio comportamiento para acomodar el widget y a sus respectivos widgets hijos).
Vea también: jwidget_set_position.
Puede cambiar la forma de redibujar una región de un widget (jwidget_redraw_region). Por ahora sólo los managers necesitan interceptar este mensaje.
También puede cambiar la forma de "ensuciar" los widgets hijos. Por ejemplo, las list-boxes (cuadros de lista) necesitan enganchar este mensaje para redibujar únicamente los ítems que estén dentro del área de visible (para optimizar la velocidad de proceso).
Las señales son un buen método de enganchar determinadas funciones que controlan a las widgets. Es decir que podemos saber cuando ocurre determinado cambio en un widget (por ejemplo si un widget fue eliminado, o si un botón cambio de estado).
Se envia cuando un widget determinado es ensuciado.
Vea también: jwidget_dirty.
Al cambiar el estado de un widget a activado.
Vea también: jwidget_enable.
Al cambiar el estado de un widget a desactivado.
Vea también: jwidget_disable.
Vea también: jwidget_select.
Vea también: jwidget_deselect.
Vea también: jwidget_show.
Vea también: jwidget_hide.
Vea también: jwidget_add_child.
Vea también: jwidget_remove_child.
Vea también: jwidget_add_child, jwidget_remove_child.
Vea también: JI_SIGNAL_SET_TEXT.
Vea también: JI_SIGNAL_GET_TEXT.
Vea también: jwidget_init_theme.
Vea también: jmanager_new.
Vea también: jmanager_free.
Vea también: jmanager_new.
Vea también: jmanager_poll.
Vea también: jmanager_run.
Vea también: jmanager_dispatch_messages.
Vea también: jmanager_set_focus.
Vea también: jmanager_set_mouse.
Vea también: jmanager_set_capture.
Vea también: jmanager_get_focus.
Vea también: jmanager_get_mouse.
Vea también: jmanager_get_capture.
Vea también: jwidget_magnetic.
Vea también: jmanager_set_focus, ji_manager_set_mouse, ji_manager_set_capture.
Una ventana es un tipo de widget especial en una caja rectangular que representa un cuadro de diálogo (entre el usuario y el programa) el cual el usuario puede mover o cambiar de tamaño a su antojo.
En Jinete, la ventana incluye sólo los rebordes y la barra de título, usted debe agregarle los widgets hijos mediante jwidget_add_child. La posición de los hijos es puesta en el área cliente (el área dentro de los bordes de la ventana), por lo que deberá agregar sólo un widget dentro de la ventana (generalmente una caja (box)) la cual contendrá los demás widgets.
Vea también: jwindow_is_desktop.
Vea también: jwindow_close.
Vea también: jwindow_open, jmanager_open_window.
Esta función generalmente no es necesaria utilizarla si usted usa jwindow_center o jwindow_position antes. Será necesaria en casos especiales donde usted necesite saber el tamaño mínimo que necesita la ventana antes de abrirla.
Vea también: jwindow_position.
No debería usar esta función a menos que sepa lo que está haciendo. Generalmente nunca la deberá llamar directamente, en cambio, las funciones jwindow_open_fg o jwindow_open_bg son las comúnmente utilizadas (y las mismas suelen utilizar jwindow_open).
Vea también: jwindow_open_fg, jwindow_open_bg, ji_get_default_manager, jmanager_poll.
Útil cuando necesita hacer cosas como:
jwindow_open_fg (window); if (jwindow_get_killer (window) == boton_aceptar) { ... } jwidget_free (window);
Vea también: jwindow_open_bg, jwindow_get_killer, jwidget_free.
Esta función sólo coloca la bandera auto-destroy a la ventana y llama a la función jwindow_open. La bandera auto-destroy hace que la ventana, al ser cerrada, sea automáticamente liberada (jwidget_free) por el mismo manager antes que por nosotros.
Vea también: jwindow_open, jwindow_open_fg, jwidget_free, jwidget_autodestroy.
Vea también: jwindow_open, jwindow_get_killer.
Vea también: jwindow_open_fg.
Vea también: jwindow_new_desktop.
Una caja (box) es uno de los widgets más sencillos de manejar y a su vez, uno de los más útiles. Sirve para disponer los widgets hijos de forma horizontal o vertical, acomodándolos a nuestro antojo, pero sin tener que preocuparnos por el tamaño que necesita cada widget en particular.
"align" debe poseer uno de estos dos valores:
Un botón es un widget que al ser presionado cierra la ventana donde está, ó ejecuta alguna acción o comando (como abrir otra nueva ventana).
Un botón, sin que usted intercepte ninguna señal, ni mensaje, siempre cerrará la ventana, tal es así, que luego puede preguntar por jwindow_get_killer() y le devolverá un puntero a dicho botón.
Hay muchas formas de cambiar este comportamiento por defecto, la más cómoda es utilizando las funciones ji_button_add_command, así la ventana no será cerrada y en su lugar se llamará al comando especificado. También, utilizando jwidget_add_hook() puede interceptar el mensaje JM_SIGNAL cuando se envía la señal JI_SIGNAL_BUTTON_SELECT.
Para que no queden dudas, cuando un botón es presionado:
Puede saber que botón cerró la ventana utilizando jwindow_get_killer.
Vea también: jbutton_add_command, jwindow_get_killer.
Vea también: jbutton_add_command_data, JI_SIGNAL_BUTTON_SELECT.
Vea también: jbutton_add_command, JI_SIGNAL_BUTTON_SELECT.
Esta señal se envía a los handlers del botón cuando el mismo es presionado (seleccionado). Deberá retornar TRUE para indicar que utilizó dicha señal, si es que no quiere ejecutar el comportamiento por defecto del botón: llamar los comandos si es que existen o cerrar la ventana en caso contrario.
Vea también: Button (botón), jwidget_add_hook.
En un archivo .jid puede definir la estructura de una ventana (o de cualquier tipo de widget).
Ejemplo:
En "archivo.jid":
En un "archivo.c":<window desktop name="ventana1" text="Mi Ventana"> <box vertical> <label expansive name="mensaje" text="Su mensaje" /> <box horizontal homogeneous> <button text="&Aceptar" name="boton_aceptar" /> <button text="&Cancelar" /> </box> </box> </window>
JWidget ventana1 = ji_load_widget ("archivo.jid", "ventana1"); JWidget boton_aceptar = jwidget_find_name (ventana1, "boton_aceptar"); jwindow_open_fg (ventana1); if (jwindow_get_killer (ventana1) == boton_aceptar) { ... }
Las listas enlazadas se manejan a través de los punteros JList:
La estructura jlist se define:typedef struct jlist *JList;
La mayoría de funciones reciben como primer parámetro el puntero al primer elemento de la lista (el cual puede estar apuntado a NULL) y devuelven un nuevo puntero (por las dudas si la cabecera cambió).struct jlist { void *data; JList next; JList prev; };
Por ejemplo:
Generará la lista (1, 2, 3).JList lista = NULL; lista = jlist_append (lista, (void *)2); lista = jlist_append (lista, (void *)3); lista = jlist_prepend (lista, (void *)1); jlist_free (lista);
(Nota: si alguna vez programó con la librería GLib, las funciones g_list_* hacen exáctamente lo mismo que sus respectivas jlist_*).
Vea también: jlist_free_1.
Vea también: jlist_free, ji_list_alloc.
Vea también: jlist_delete_link, ji_list_free_1.
Vea también: jlist_remove_link.
Esta función recorre desde "list" hacia delante.
Retorna -1 si no se encontró.
Vea también: jlist_index.
Retorna -1 si no se encontró.
Vea también: jlist_position.
Imprime:void mi_funcion (void *data, void *user_data) { printf ("%d\n", (int)data); } ... JList lista = NULL; lista = jlist_append (lista, (void *)2); lista = jlist_append (lista, (void *)3); lista = jlist_prepend (lista, (void *)1); jlist_foreach (lista, mi_funcion, NULL); jlist_free (lista);
1 2 3
struct jrect { int x, y, w, h; };
Vea también: jrect_free.
Vea también: jrect_new, jrect_copy.
Vea también: jrect_new.
Vea también: jrect_new_copy.
Vea también: jrect_has_intersection.
Vea también: jrect_stretch.
Vea también: jrect_shrink.
Vea también: jrect_intersect.
En Jinete, una región es un conjunto de rectángulos, una lista enlazada de rectángulos.
typedef struct jregion JRegion; struct jregion { JList rects; };
Vea también: jregion_free.
Vea también: jregion_new.
Vea también: jregion_new, ji_region_clear.
Vea también: jregion_free.
Jinete comenzó con Allegro Sprite Editor (ASE) y continuará muy cerca de él. Vea la página de ASE para tener noticias sobre esta librería:
Si quiere saber más sobre el autor:
http://www.davidcapello.com.ar/
Gracias a: