View
Funciones
View* | view_create (void) |
View* | view_scroll (void) |
void | view_data (...) |
type* | view_get_data (...) |
void | view_size (...) |
void | view_OnDraw (...) |
void | view_OnSize (...) |
void | view_OnEnter (...) |
void | view_OnExit (...) |
void | view_OnMove (...) |
void | view_OnDown (...) |
void | view_OnUp (...) |
void | view_OnClick (...) |
void | view_OnDrag (...) |
void | view_OnWheel (...) |
void | view_OnKeyDown (...) |
void | view_OnKeyUp (...) |
void | view_OnFocus (...) |
void | view_keybuf (...) |
void | view_get_size (...) |
void | view_content_size (...) |
void | view_scroll_x (...) |
void | view_scroll_y (...) |
void | view_viewport (...) |
void | view_point_scale (...) |
void | view_update (...) |
Los controles View o vistas personalizadas (Figura 1) son áreas en blanco dentro de la ventana que nos permiten implementar nuestros propios componentes. Tendremos total libertad para dibujar y capturar los eventos del teclado o ratón que nos permitan interactuar con la misma.
- Utiliza view_create para crear una vista.
- Utiliza view_data para vincular un objeto.
- Utiliza view_get_data para obtener este objeto.
- Utiliza view_size para establecer el tamaño por defecto.
1. Dibujar en vistas.
No podemos actualizar el área de dibujo cuando queramos. Esta puede verse afectada por otras ventanas del entorno, por lo que el framebuffer es gestionado directamente por el sistema operativo. Este último mandará una notificación cada vez que el control deba refrescar su contenido.
- Utiliza view_OnDraw para establecer la función de dibujo.
- Utiliza view_update para forzar la actualización del contenido.
En Die tienes una sencilla aplicación de ejemplo que implementa el dibujado de vistas personalizadas. En ella se representa la figura de un dado, permitiéndonos editar ciertos parámetros del dibujo. Esta interacción irá lanzando una serie de eventos que requerirán el re-dibujado de nuestra figura. El ciclo completo puede resumirse en estos pasos (Figura 2):
- Se produce algún evento que requiere actualizar el contenido de la vista.
- La aplicación llama al método view_update para notificar que la vista debe ser actualizada.
- En el momento oportuno, el sistema mandará un evento
OnDraw
con un contexto DCtx listo para dibujar. Aquí puedes aplicar todo lo visto en Draw2D y utilizar líneas, figuras o textos para representar el contenido del control.
El sistema operativo puede lanzar eventosOnDraw
en cualquier momento sin que hallamos llamado previamente aview_update
.
2. Vistas con scroll
Es posible que la "escena" a representar sea mucho más grande que el propio control, por lo que este mostrará solo un pequeño fragmento de la misma (Figura 3). En estos casos diremos que la vista es un viewport de la escena. Podemos gestionarlo de dos maneras:
- Utilizar draw_matrixf para indicar la transformación que integra el desplazamiento, zoom y posible rotación del viewport con respecto a la escena. Todo ello debe ser gestionado por la aplicación y no tenemos que hacer nada especial, salvo llamar a
view_update()
cuando sea necesario. - Utilizar barras de scroll que permitan al usuario desplazarse libremente por el contenido. En este caso la gestión de la vista se complica un poco más. Esto es lo que debemos tener en cuenta:
- Utilizar view_scroll para crear la vista.
- Utilizar view_content_size para indicar las medidas de la escena, con el fin de que se dimensionen correctamente las barras laterales.
- Utilizar view_scroll_x, view_scroll_y para mover el origen del área visible.
- Utilizar view_viewport para obtener la posición y dimensiones del área visible.
Algo muy importante es evitar dibujar elementos no visibles, sobre todo en escenas muy grandes o con multitud de objetos. El sistema operativo mandará sucesivos eventos OnDraw()
a medida que el usuario manipule las scrollbars, indicando en la estructura EvDraw los parámetros del área visible. En https://nappgui.com/es/howto/drawbig.html tienes una aplicación de ejemplo que muestra como gestionar correctamente este tipo de casos.
Es posible que las dimensiones del viewport recibido enOnDraw()
sean algo superiores a las medidas reales devueltas porview_viewport()
. Esto es debido a que determinados sistemas (macOS, Linux) obligan a dibujar en ciertas zonas no visibles cercanas a los bordes, con el fin de evitar parpadeos en desplazamientos muy rápidos.
3. Uso del ratón
Para poder interactuar con el control es necesario definir manejadores para los diferentes eventos del ratón (Figura 4). El sistema operativo notificará las acciones del usuario con el fin de que la aplicación pueda lanzar las acciones pertinentes. No es necesario utilizarlos todos, tan solo los imprescindibles en cada caso.
- Utiliza view_OnEnter para saber cuando el cursor entre en la vista.
- Utiliza view_OnExit para saber cuando el cursor salga de la vista.
- Utiliza view_OnMove para saber cuando el cursor se está moviendo por la vista.
- Utiliza view_OnDown para saber cuando se pulse un botón dentro de la vista.
- Utiliza view_OnUp para saber cuando se libere un botón dentro de la vista.
- Utiliza view_OnClick para identificar un click (Up + Down rápido).
- Utiliza view_OnDrag para desplazamientos del cursor con un botón pulsado.
- Utiliza view_OnWheel para el uso de la ruedecilla del ratón.
Si la vista utiliza barras de scroll, la posición (x,y) del cursor pasada a EvMouse en cada evento, hace referencia a los coordenadas globales de la escena, teniendo en cuenta el desplazamiento. En vistas sin barras de scroll, son las coordenadas locales del control.
4. Uso del teclado
Para poder recibir eventos de teclado, es necesario que la vista sea capaz de obtener el foco, algo que por defecto está desactivado.
- Utiliza layout_tabstop para incluir la vista en el tab-list de la ventana y permitir que reciba el foco del teclado mediante la tecla
[TAB]
o al hacer clic sobre ella. - Utiliza view_OnKeyDown para detectar cuando se pulse una tecla.
- Utiliza view_OnKeyUp para detectar cuando se libere una tecla.
- Utiliza view_OnFocus para notificar a la aplicación cada vez que la vista reciba (o pierda) el foco del teclado. En (Figura 5), la vista cambia el color de la celda activa cuando tiene el foco.
En los eventos KeyDown
y KeyUp
se recibirá un vkey_t con el valor de la tecla pulsada. En (Figura 6) y (Figura 7) se muestran la correspondencia de estos códigos.
En Aplicaciones síncronas es posible que necesitemos saber si una tecla está pulsada o no durante el ciclo de actualización (síncrono) donde no tenemos acceso a los eventos OnKeyDown
y OnKeyUp
(asíncronos). Esto es posible hacerlo asignando a la vista un búfer de teclado mediante view_keybuf, que capturá los eventos asociados a cada tecla y nos permitirá consultar su estado en cualquier momento de forma cómoda.
view_create ()
Crea una nueva vista personalizada.
View* view_create(void);
Retorna
El control vista.
view_scroll ()
Crea una nueva vista con barras de scroll.
View* view_scroll(void);
Retorna
El control vista.
view_data ()
Asocia datos de usuario con la vista.
void view_data(View *view, type **data, FPtr_destroy func_destroy_data, type);
view | La vista. |
data | Datos de usuario. |
func_destroy_data | Destructor de los datos de usuario. Será llamado al destruir la vista. |
type | Tipo de datos de usuario. |
view_get_data ()
Obtiene los datos de usuario asociados con la vista.
type* view_get_data(const View *view, type);
view | La vista. |
type | Tipo de datos de usuario. |
Retorna
Los datos de usuario.
view_size ()
Establece el tamaño por defecto de la vista.
void view_size(View *view, const S2Df size);
view | La vista. |
size | El tamaño. |
Observaciones
Corresponde al Dimensionado natural del control. Por defecto 128x128.
view_OnDraw ()
Establece un manejador para dibujar en la vista.
void view_OnDraw(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cada vez que deba refrescarse el dibujo. |
Observaciones
Ver Eventos GUI.
view_OnSize ()
Establece un manejador para el cambio de tamaño.
void view_OnSize(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cada vez que la vista cambie de tamaño. |
Observaciones
Ver Eventos GUI.
view_OnEnter ()
Establece un manejador para la entrada del ratón.
void view_OnEnter(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando el cursor del ratón entre en el área de la vista. |
Observaciones
Ver Eventos GUI.
view_OnExit ()
Establece un manejador para la salida del ratón.
void view_OnExit(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando el cursor del ratón salga del área de la vista. |
Observaciones
Ver Eventos GUI.
view_OnMove ()
Establece un manejador para el movimiento del ratón.
void view_OnMove(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará a medida que el cursor del ratón se desplace por encima de la vista. |
Observaciones
Ver Eventos GUI.
view_OnDown ()
Establece un manejador para la pulsación de un botón del ratón.
void view_OnDown(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se pulse un botón. |
Observaciones
Ver Eventos GUI.
view_OnUp ()
Establece un manejador para la liberación de un botón del ratón.
void view_OnUp(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se libere un botón. |
Observaciones
Ver Eventos GUI.
view_OnClick ()
Establece un manejador para el clic del ratón.
void view_OnClick(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cada vez que se haga clic sobre la vista. |
Observaciones
Ver Eventos GUI.
view_OnDrag ()
Establece un manejador para el arrastre del ratón.
void view_OnDrag(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará mientras se esté arrastrando el cursor del ratón sobre la vista. |
Observaciones
"Arrastrar" es desplazar el ratón con uno de los botones pulsados. Ver Eventos GUI.
view_OnWheel ()
Establece un manejador para la ruedecilla del ratón.
void view_OnWheel(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se mueva la ruedecilla del ratón sobre la vista. |
Observaciones
Ver Eventos GUI.
view_OnKeyDown ()
Establece un manejador para la pulsación de una tecla.
void view_OnKeyDown(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se pulse una tecla y la vista tenga el foco del teclado. |
Observaciones
Ver Eventos GUI.
view_OnKeyUp ()
Establece un manejador para la liberación de una tecla.
void view_OnKeyUp(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se libere una tecla y la vista tenga el foco del teclado. |
Observaciones
Ver Eventos GUI.
view_OnFocus ()
Establece un manejador para el foco del teclado.
void view_OnFocus(View *view, Listener *listener);
view | La vista. |
listener | Función callback que se llamará cuando se reciba o se pierda el foco del teclado. |
Observaciones
Ver Uso del teclado y Eventos GUI.
view_keybuf ()
Establece un búfer de teclado para la consulta síncrona o asíncrona del estado de las teclas.
void view_keybuf(View *view, Keybuf *buffer);
view | La vista. |
buffer | Bufer de teclado que será mantenido por la vista, capturando los eventos |
Observaciones
Solo mantiene una referencia al búfer, que deberá ser destruido por el objeto que lo creó. Ver Búfer de teclado. La aplicación podrá seguir recibiendo eventos de teclado a través de view_OnKeyDown y view_OnKeyUp.
view_get_size ()
Obtiene el tamaño actual de la vista.
void view_get_size(const View *view, S2Df *size);
view | La vista. |
size | El tamaño. |
view_content_size ()
Establece el tamaño del área de dibujo cuando existen barras de scroll.
void view_content_size(View *view, const S2Df size);
view | La vista. |
size | El tamaño interno del área de dibujo. |
Observaciones
Cuando se crea una vista con scroll, este método indica la totalidad del área de dibujo. El control lo utilizará para dimensionar y posicionar las barras de scroll.
view_scroll_x ()
Desplaza la barra de scroll horizontal.
void view_scroll_x(View *view, const real32_t pos);
view | La vista. |
pos | Nueva posición de la barra horizontal. |
view_scroll_y ()
Desplaza la barra de scroll vertical.
void view_scroll_y(View *view, const real32_t pos);
view | La vista. |
pos | Nueva posición de la barra vertical. |
view_viewport ()
Obtiene las dimensiones del área visible de la vista.
void view_viewport(const View *view, V2Df *pos, S2Df *size);
view | La vista. |
pos | La posición del viewport. Puede ser |
size | El tamaño del viewport. Puede ser |
Observaciones
Si la vista no tiene barras de scroll, pos
será (0,0)
.
view_point_scale ()
Obtiene el escalado del punto.
void view_point_scale(const View *view, real32_t *scale);
view | La vista. |
scale | El escalado. |
Observaciones
El tamaño de la vista y coordenadas de dibujo se expresan en puntos, que normalmente corresponden con píxeles (1pt = 1px). En Pantallas retina puede ocurrir que (1pt = 2px). Si bien los Contextos 2D gestionan esto automáticamente, es posible que necesitemos saber la cantidad de píxeles para crear otro tipo de framebuffers (OpenGL, DirectX, etc). Pixels = view_get_size * view_point_scale.
view_update ()
Manda una orden al sistema operativo que la vista debe ser refrescada.
void view_update(View *view);
view | La vista. |