Posicionamiento dinámico de controles en formularios

Estoy buscando información acerca del posicionamiento o reordenación de controles dentro del formulario, y hasta ahora, lo más aproximado que he visto es el post Posición de control en formulario ¿Es posible su control?.

La pregunta es si es posible, y en caso afirmativo de qué forma, el distribuir los controles en el formulario de manera dinámica. Me explico: supongamos un formulario con 20 controles, 10 nombres de campo y 10 campos de edición de texto y se pretende que los controles, o bien no estiren, o bien aunque puedan estirar que lo hagan hasta un tamaño máximo. Si todos estos campos se distribuyen verticalmente de dos en dos, el espacio libre a la derecha de los mismos (suponiéndolos alineados a la izquierda) quedaría visualmente mal, de igual modo, si los controles se estirasen a la totalidad del tamaño de la ventana seguirían siendo visualmente inadecuados. Podríamos agrupar estos controles en lugar de dos, de cuatro, pero esto además del problema del estirado, que no sería grave para pantallas pequeñas, ya sí se vería mal con pantalla grande que igualmente estirarían demasiado, pero es que además se suma el inconveniente de que el formulario se podrá reducir como mínimo al tamaño de la suma de los controles contenidos, con lo que si se diseña para una pantalla media, en una pequeña el formulario podría sobrepasar el área visible.
Entonces, ¿Hay alguna forma de que los controles rellenen automáticamente hasta el largo de la ventana, y los que no quepan en horizontal se pasen a la fila siguiente?. Imaginemos el ejemplo de una ventana de navegador web sobre una página responsive, los contenedores o div se estiran y/o encogen un mínimo y un máximo definido, a partir de ahí, por medio del CSS se puede modificar el comportamiento y que, si la ventana es grande los controles ocupen una posición, y si esta se reduce, dichos controles se mueven de sitio para para no tener que estirar/encoger más de un tamaño óptimo.
En las imágenes adjuntas intento transmitir este concepto, así en la imagen Ventana Horizontal sería un ejemplo de como quisiera que quedasen los controles cuando el usuario redimensiona la ventana en horizontal, de igual modo, para cuando redimensiona en vertical en la otra imagen. Lógicamente, habrá unas medidas y/o posiciones de controles mínimas o básicas, es decir, habría que programarlo pensando en la ventana de menor tamaño en la que se podría abrir la aplicación, pero a partir de ahí, al redimensionar a mayor que los controles se moviesen para ocupar todo el espacio horizontal sin que tengan que estirarse en demasía.

¿Alguna sugerencia?

image

image

Para solucionar eso están los layouts que ordenan los controles y permiten estirar.

Si, pero los layouts únicamente me permiten organizar en vertical, en horizontal o en grid, pero eso conlleva, por ejemplo si ponemos horizontal, pondrá todos los controles que hayamos incluido dentro alineados uno a continuación del otro, con lo que forzará el tamaño mínimo del formulario. Lo mismo ocurre con el vertical. Entonces, hablando del ejemplo anterior si pongo los 10 controles dentro de un layout horizontal, el formulario se me sale del área visual de la pantalla, siendo el tamaño mínimo de redimensionado el que sumen todos los controles de ese layout.

Quizás debido a mi desconocimiento de la herramienta no los esté usando adecuadamente, pero he hecho pruebas con todos los tipos de alineamiento, las diferentes opciones de ancho y de alto y conjugaciones de estos pero no consigo el efecto deseado.
Tampoco en los manuales encuentro ninguna referencia a esta propiedad.

Hola gAb.

Definitivamente hacer eso con layouts no se puede. Éstos solo permiten organizar los controles con un número de filas y columnas preestablecido y sin posibilidad de cambiarlo en tiempo de ejecución.

Con Velneo, ahora mismo, no podemos (nativamente) diseñar pantallas Responsive que son las que tú quieres obtener.

Lo más parecido que tiene Velneo a lo que planteas sería un Objeto Casillero en el que las columnas y filas mostradas se adaptan al espacio disponible, desbordando en horizontal o vertical según lo hayas especificado en vDevelop.

Saludos
Paco Satué

Bien, entonces no queda sino ir jugando con la distribución y el largo de los controles para adaptarlo medianamente.

Otra pregunta, ¿Y saber las dimensiones de la ventana en tiempo de ejecución?, ¿Es posible? Porque si fuese posible, podría crear el formulario teniendo en cuenta la distribución horizontal y colocar los controles por ejemplo para dos tamaños de pantalla intermedios, otro para la distribución vertical igual colocando los controles para esa distribución (duplicando los controles) y luego en tiempo de ejecución solamente mostrar aquellos que coincidan con el tamaño de pantalla actual.

Hola gAb.

La clase theMainWindow del API te proporciona el tamaño de la Ventana de vClient en cualquier momento.

Lo que planteas de mostrar/ocultar objetos es lo que se utiliza en las Tablets/Móviles para que la aplicación soporte dignamente la rotación Horizontal/Vertical.

Un ejemplo sencillo:

function fijar_ancho() {
        // Esta función se ejecuta cada vez que redimensionamos la pantalla (evento Ventana redimensionada)
	var nAnchoWin = theMainWindow.width()
	var nAltoWin = theMainWindow.height()
        // Ancho por debajo del cual se muestran/ocultan algunos controles del formulario
	var nAnchoMinimoCtrl = theApp.globalVarToInt("MiApp_dat/APP_WIN_ANCHO_CONTROL")
        // Ancho por debajo del cual se muestran/ocultan Barras de Botones
	var nAnchoMinimoBtn = theApp.globalVarToInt("MiApp_dat/APP_WIN_ANCHO_BOTONES")
        // Obtenemos la relación Ancho/Alto para determinar cuándo debemos mostrar/ocultar controles
	var lMostrarControl = nAnchoWin > nAnchoMinimoCtrl
        // La variable global APP_WIN_CONTROL_VISIBLE controlará la visualización dinámica de los Controles 
	theApp.setGlobalVar("MiApp_dat/APP_WIN_CONTROL_VISIBLE", lMostrarControl)
	if (nAnchoMinimoBtn) {
		// Podemos también mostrar y ocultar Barras de Botones
		var lOcultarBotones = nAnchoWin < nAnchoMinimoBtn
		if (lOcultarBotones) {
                        // Mostrar la Barra de Botones Horizontal
			theMainWindow.showDock("BARRA_BOTONES_H")
                        // Ocultar la Barra de Botones Vertical
			theMainWindow.hideDock("BARRA_BOTONES")
		} else {
                        // Ocultar la Barra de Botones Horizontal
			theMainWindow.hideDock("BARRA_BOTONES_H")
                        // Mostrar la Barra de Botones Vertical
			theMainWindow.showDock("BARRA_BOTONES")
		}
	}
}

Este sistema funciona bien, pero para formularios complejos no te lo aconsejo porque Velneo no tiene herramientas avanzadas para la edición gráfica de los formularios (bloqueo de controles, ocultar layouts, zoom, etc …). Además duplicar controles te va a exigir mucho control añadido en tu código.

En resumen, este es un aspecto que debe mejorar mucho en Velneo si quiere competir en el cada vez más sofisticado mundo de la movilidad.
Solo hay que echar un vistazo a las increibles proezas gráficas que se ven hoy en día en cualquier APP Store.

Saludos
Paco Satué

Hombre, yo supongo que esto no es la primera vez que se les plantea y ellos ya habrán tomado nota. Ahora lo que falta es esperar que tenga la prioridad suficiente como para entrar en futuras versiones.

Miraré la opción que propones a ver que tal, pero así a bote pronto se me antoja que va a ser un tostón a menos que encuentre la forma de que un único código sea reutilizable por varios formularios, porque si no, como bien dices no merece la pena por la cantidad de código si es que se debe hacer una función para cada formulario.

Muchas gracias

Hola gAb.

Para que la función sea reutilizable, únicamente debes capturar el evento Ventana redimensionada en un formulario que tengas incrustado en un dock de tu aplicación. El dock siempre te indicará cuándo se está cambiando el tamaño de la Ventana principal.

Necesitamos esto porque la ventana de vClient ¡¡ no dispone del evento Ventana redimensionada !!.

Saludos
Paco Satué

Bueno, entonces no parece muy complicado. Si capturo las dimensiones de la ventana en dos variables globales Largo y Ancho, simplemente les pongo a los controles la condición de visibilidad en función del valor de estas variables y no tendría que hacer más procesos que el propio del dock para capturar el redimensionado. ¿Voy bien encaminado? Entiendo que el evento de visibilidad se desencadena al variar el valor de la fórmula con la que esté construido ¿No?

Hola Gabriel.

Efectívamente, la visibilidad se controla mediante la variable global APP_WIN_CONTROL_VISIBLE que has asignado a la propiedad Visible de los controles implicados en la funcionalidad Responsive.

Esa variable global APP_WIN_CONTROL_VISIBLE valdrá 0 o 1 según el cáculo que hagas cada vez que se desencadena el evento Ventana redimensionada del formulario incrustado en el dock. Yo te he puesto un ejemplo, pero ya tú diseñas la lógica adecuada.

Saludos
Paco Satué

Gracias Paco, aún no lo he probado, pero iré comentando cómo queda.

Saludos

Bueno, esto tiene más inconvenientes que ventajas.

Siguiendo tus sugerencias creé un formulario vacío de tamaño mínimo y lo coloqué en un dock aparcado arriba. Al formulario le conecté la señal de “Ventana redimensionada” al manejador de eventos “Resize”, dentro del cual incluí únicamente las dos sentencias “theApp.setGlobalVar(“MiAppCode.vcd/LARGO”, theMainWindow.width())” y “theApp.setGlobalVar(“MiAppCode.vcd/ALTO”, theMainWindow.height())”. Y finalmente en el formulario que quiero controlar, únicamente le pongo la condición de visibilidad al control deseado en función de si el Largo o el Alto tienen más de x.
Esto plantea una nueva duda: ¿Y si se redimensiona sólo en vertical? El formulario del control de Resize no se va a enterar ya que él no se está redimensionando puesto que el movimiento vertical no le afecta.
La solución puede ser colocar otro formulario Resize en otro dock aparcado a la izquierda.
Hasta aquí bien, ahora si se redimensiona en un solo sentido o lo detecta uno o lo detecta el otro, pero hay otra duda más. ¿Y si el usuario cierra estos formularios o los cambia de ubicación (por ej.: los dos a la izquierda), o los pone en modo ventana? Pues ya no se detecta el movimiento, o se detecta mal si los pone los dos en vertical o en horizontal.

Una posible solución podría ser incluir en estos formularios botones con los accesos del menú y ocultar el menú, así siempre está obligado a mostrar estos formularios, pero aún así quedaría la posibilidad de que los aparque los dos en el mismo lado y entonces ya no se controla el movimiento en ese sentido.

Habrá que seguir investigando…

Hola Gabriel.

Bien, ya veo que vas comprendiendo que te has metido en un terreno fanganoso y desconocido.

Requisitos para que funcionara bien esta nueva funcionalidad:

  • que los Docks de tipo Toolbar se puedan bloquear -> Este requisito NO SE CUMPLE
  • … o que los Docks de tipo Dock se puedan bloquear → Este requisito SE CUMPLE pero muestra siempre una barra de título
  • … o que la Ventana principal de vClient tenga la señal “Ventana redimensionada” → Este requisito NO SE CUMPLE

La pregunta es ¿cómo detectar en Velneo de manera fiable que se ha redimensionado la Ventana de vClient?
Bienvenido al mundo del “Prueba y error” con Velneo.

De todas formas yo uso las Toolbars y nunca he tenido problemas con que el Usuario las mueva de sitio. En cualquier caso siempre está la opción de reiniciar la aplicación y recolocar todo en su sitio.

Saludos
Paco Satué

En la ToolBar no se puede incluir procesos. Pero si pongo los dock que contienen los formularios de control vertical y horizontal sin ningún contenido, dimensionados al mínimo, quedan medianamente decentes, o sea, queda una línea horizontal superior y una vertical lateral izquierda, que podrían pasar por buenas, ya que son lo suficientemente estrechas, pero el problema es que si un dock que contiene un formulario se pone como ToolBar deja de percibir los movimientos de redimensionado de la ventana, así que sigo dentro del mismo pozo.

Así pues, habrá que echarse mucho colirio en los ojos para que ese efecto del estirado de los controles, o el ver los controles en una esquinita y el resto vacío nos parezca menos irritante.

Saludos