Activar Vista dinámicamente


([N3] pacosatu) #1

Hola.

Me imagino que habrá muchos desarrolladores que pensarán que el sistema de gestión de las Vistas en Velneo es claramente insuficiente. Ha salido algún añadido, como el script que impide la apertura de la misma Vista varias veces, que por cierto podrían añadirlo también a vDevelop.

Os planteo una situación en la que el uso de Vistas es muy práctico y necesitamos un cierto control sobre las Vistas Abiertas.
Imaginaros una Vista principal con la Lista de Pedidos del cliente FRM_PEDIDOSLISTA. Este formulario se ejecuta en modo Vista una sola vez desde el menú de la Aplicación. Desde la rejilla de pedidos de FRM_PEDIDOSLISTA el usuario puede hacer doble-click para ir abriendo en modo Vista uno o varios pedidos FRM_PEDIDO. Esto le permite al usuario cambiar rápidamente entre los pedidos seleccionados.

El comportamiento que quiero arreglar es que cuando se cierra la Vista del Pedido FRM_PEDIDO se active automáticamente la Vista correspondiente a FRM_PEDIDOSLISTA. El comportamiento por defecto de Velneo es activar la Vista inmediatamente anterior y esto muchas veces produce confusión al usuario. Esto se complica si además tenemos otra Lista en pantalla, por ejem la Lista de Albaranes .

Si has abierto el Pedido desde la Rejilla de Pedidos, el usuario espera que al cerrar el Pedido se vuelva a la lista de Pedidos.

Mi solución a este problemilla es la siguiente (lo siento, pero hay que usar JavaScript):

Primero el código heredable.

Funcion: FUN_VISTA_GUARDAR()
Esta función nos devuelve el identificativo del formulario que ha llamado al formulario actual
Por ejemplo: FRM_PEDIDO es llamado por FRM_PEDIDOSLISTA


Rem ( Se llama desde el PRE-INIT de los formularios )
Rem ( Guarda en _CID_VISTA_ORIGEN el Identificativo de la Vista desde la que se abre el Formulario actual )
Rem ( Todos los formularios deberán tener una variable Local _CID_FORMULARIO que identifique el formulario )
Crear manejador de objeto ( hVista, Proceso PRO_VISTA_GUARDAR_JS@0PS__Sistema_app )
Disparar objeto ( hVista, 1º plano: Local (síncrono), )
Libre
Get variable local de objeto ( hVista, CID_VISTA_ACTIVA, CRESULTADO )
Set dato de retorno ( CRESULTADO )

Proceso JavaScript PRO_VISTA_GUARDAR_JS


// Llamado desde la función FUN_VISTA_GUARDAR
// Devolver el identificativo único de la Vista activa que está guardado en la variable local _CID_FORMULARIO
var cIDActiva = theMainWindow.currentView().root().varToString("_CID_FORMULARIO")
theRoot.setVar("CID_VISTA_ACTIVA",cIDActiva)


Proceso JavaScript PRO_VISTA_EVENTOCERRAR_JS
// Activa la Vista, si existe, con identificativo _CID_VISTA_ORIGEN
var cIDFormulario = theMainWindow.currentView().root().varToString("_CID_FORMULARIO")
var cIDActivar = theMainWindow.currentView().root().varToString("_CID_VISTA_ORIGEN")
if (cIDActivar) {
	theMainWindow.showMessageStatusBar("Cerrando " + cIDFormulario,1000)
	var oVista = null;
	var numVistas = theMainWindow.viewsCount();
	for (numVista = 0; numVista < numVistas; numVista++){
		oVista = theMainWindow.getViewAt(numVista);
		if (oVista.root().varToString("_CID_FORMULARIO") == cIDActivar){
			theMainWindow.setCurrentView(oVista)
			break
		};
	};
}

Ahora el código que debe ir en los formularios.

  • Formularios principales (ejem. FRM_PEDIDOSLISTA, …)
    Añadir variable local _CID_FORMULARIO
    Manejador del evento pre-Inicializado en todos los formularios principales

Manejador de Evento: PRE_INI
Rem ( Identificamos el formulario para activarlo desde las Vistas que éste llama )
Set ( _CID_FORMULARIO, "FRM_" + timeToString(currentTime(), "HHmmsszzz") )

  • Formularios secundarios (ejem. FRM_PEDIDO, …)
    Añadir variable local _CID_FORMULARIO y _CID_VISTA_ORIGEN
    Manejador del evento pre-Inicializado en los formularios llamados desde el formulario principal

Manejador de Evento: PRE_INI
Rem ( Identificamos el formulario para activarlo desde las Vistas que éste llama )
Set ( _CID_FORMULARIO, "FRM_" + timeToString(currentTime(), "HHmmsszzz") )
Rem ( Guarda el identificativo de la Vista actual para volver a ella cuando cerramos esta Vista )
Set ( _CID_VISTA_ORIGEN, fun:FUN_VISTA_GUARDAR@0PS__Sistema_app.app() )

Por último añadimos un manejador al evento Pre-Vista cerrada del marco Autoexec


Rem (Se va a cerrar una Vista. Recuerda que si devuelve 0 evitamos el cierre de la Vista (control de la X))
Ejecutar proceso ( PRO_VISTA_EVENTOCERRAR_JS@0PS__Sistema_app, 1º plano: Local (síncrono), LOK, , )

Los formularios modales NO disparan el evento Pre-Vista cerrada, por lo tanto no hay problema.
Esto funciona con varios niveles, por ejemplo desde FRM_PEDIDO1 podemos abrir la Ficha del cliente FRM_CLIENTE1 y al cerrar éste se activará la Vista con el pedido FRM_PEDIDO1.
Y esto es todo.

Probadlo y espero sea útil
Saludos
Paco Satué


([N2] AyudaVelneo) #2

Hola a todos:

Si queréis voy recogiendo los “donativos” de los que queráis para invitar el LIS 2015 a Paco Satué por el trabajo que realiza en el foro…

jajajaja

¡Vaya máquina maestro Satué!

¿Tu no serás funcionario no?

Un saludo para todos


([N4] juanjo) #3

La verdad es que para los que empanzamos a utilizar js se está convirtiendo en la WikiSatue
Juanjo


([N1] percyleoncio) #4

Doy fe de ello, siempre paro pendiente de sus consejos a lo menos en js.

Mis respetos maestro Satué


([N3] chechualta) #5

la verdad es que cuando ves la foto de Paco en el foro instintivamente abres para ver que se le ha ocurrido esta vez

Saludos y muchas gracias


([N2] ramiro) #6

Muchas gracias, Paco.

He probado lo que planteas y funciona perfectamente…

Puesto que en los Formularios se necesitan variables para identificar al propio Formulario y a su Padre, se podría plantear una pequeña modificación de tal manera que cada Formulario guardase (también) su propio idRef (variable A_ID_REF, cuyo valor se obtiene, como no, con Js). El identificador que llamas CID_FORMULARIO podría ser [ A_ID_REF + "___" + Variable de tiempo ]

Si tenemos el idRef del Formulario en una variable (o si lo obtenemos sobre la marcha) en cierto modo se puede lograr que los procesos Js “refactoricen” el idRef del Formulario:

Quizás se vea mejor con un ejemplo:

En un Formulario uso procesos Js para controlar la visibilidad de una pestaña en un separador
El formulario a ocultar se llama M3_CMP_CAB___PRD_BLU y está en el proyecto Est_App

El código Js del manejador que la oculta sería este:

var For, Sep, Nom, Tab;
// Formulario, Separador y Nombre Pestaña
For = theRoot.dataView().mainForm();
Sep = For.control ( “SEP_DAT” );
Nom = “Est_App/M3_CMP_CAB___PRD_BLU” ;
//
Tab = Sep.findForm ( Nom );
if ( Tab > -1 )
{ Sep.removeForm ( Tab ); }

Si el formulario M3_CMP_CAB___PRD_BLU ejecutase esta Línea en el Pre-Init: “set _A_ID_REF = fun:GET_ID_REF@Min.dat ()” y la Función lanza un proceso V7 ligado al siguiente código Js, la función devolverá el idRef del Formulario que quedaría en la variable Local _A_ID_REF del propio Formulario

Código Js para obtener el idRef del Formulario

var idRef = theMainWindow.currentView().root().objectInfo().idRef() ;
theRoot.setVar( “A_ID_REF” , idRef ) ;

Para controlar la visibilidad de pestañas del separador DESDE EL FORMULARIO PRINCIPAL podríamos hacerlo así:

  • Leer la variable que contiene el idRef del SubFormulario
  • Ejecutar el manejador de evento que controla su visibilidad

(Más o menos como se ve en la imagen adjunta)

La Línea Nom del manejador de evento que oculta la pestaña podría ser genérica:

// Nom = “Est_App/M3_CMP_CAB___PRD_BLU” ;
Nom = theMainWindow.currentView().root().varToString ( “A_ID_REF” ) ;


Nunca entenderé que tras 16 versiones de V7 sigamos tan cojos en determinados funcionalidades de Rejillas y Formularios, que son el 95% de nuestro trabajo. Lamento, y me quejo, que tengamos que andar con estos enjuagues, pero, en fin, es lo que hay…

Al menos tenemos a Paco…

Saludos. Ramiro



([N3] pacosatu) #7

Primero gracias a todos y solo espero que esto se vaya animando cada día más.
Por supuesto, una ronda de cervezas el día 12 es mía.

Ramiro.

Estoy de acuerdo contigo que JavaScript en Velneo es un invitado poco querido por algunos, entre los que me incluyo, no por el lenguaje en sí, sino por la forma en que se ha implementado en Velneo. Quizás se hizo una implementación apresurada y poco planificada, sin tener en cuenta la refactorización (cambio automático de referencias a objetos del proyecto), con una gestión muy arcaica de ficheros js, con un editor (aunque bastante superior al de las fórmulas de Velneo) claramente insuficiente, sin un depurador imprescindible, y sobre todo obligando a los clásicos usuarios de la 6x a cambiar el paradigma de programación.

Yo elegí Velneo porque precisamente era todo lo contrario a programar como en JavaScript, pero parece ser que no podemos desligarnos de nuestro pasado.

Bueno, volviendo a tu código, ¿Lo has probado?
Veo 2 cosas que no sé si funcionan tal como las planteas.

  • Primero, en el evento PRE-INI de un formulario todavía no está activa la Vista de dicho formulario, por lo tanto, la línea
    var idRef = theMainWindow.currentView().root().objectInfo().idRef() ;
    de la función fun:GET_ID_REF@Min.dat() no delvoverá el idRef correcto.
    Para obtener el idRef() de la Vista que se abre debes guardarlo en el evento ON-SHOW.
    Recuerda que theMainWindow.currentView() no sirve para formularios en modo Diálogo.

  • Segundo, para referirte de forma dinámica un formulario de un separador usas el comando
    Nom = theMainWindow.currentView().root().varToString (“A_ID_REF”);
    Esto te daría el IdRef() del formulario Padre activo en ese momento, no del subformulario del Separador, que es lo que quieres obtener.

Compruébalo.
Saludos
Paco Satué


([N2] overBCN) #8

Gracias Paco, a esto se le llama “usabilidad”.