PuntoExe Tools Manual de Uso – Volumen 1 INTRODUCCIÓN Este Volumen 1 del Manual de Uso de las PXTools es la transcripción del primero de los cuatro videos que contienen la versión grabada del Curso de Entrenamiento dictado por el Ing. Juan Marcelo Bustamante (autor de las PXTools) a un grupo de nuevos usuarios de esta herramienta, a fines de 2007. Todas las referencias internas para la ubicación de sus contenidos temáticos o imágenes remiten al momento en que fueron abordados o mostrados en la grabación original, de modo de poder ampliar en ella cualquier asunto que pueda haber perdido claridad en la transcripción. Los títulos de cada tema hacen referencia expresa al video y momento de la reproducción en el formato: V Nº | HH:MM:SS (HoraHora:MinutoMinuto:SegundoSegundo) de modo que el índice de cada volumen permite ubicar los temas en el propio documento o en el correspondiente video indistintamente. Las imágenes se identifican con una combinación de video y momento de la reproducción en el formato: VH:MM:SS (VideoHora:MinutoMinuto:SegundoSegundo) para que puedan ser referenciadas en cualquiera de los volúmenes del manual. Con el fin de minimizar el peso de estos documentos en su versión digital, todas las imágenes contenidas tienen baja resolución, por lo que se recomienda regular el nivel de Zoom del visualizador antes de proceder a su lectura. Página 1 de 50 INDICE TEMA PuntoExe Tools Conceptos Previos al Curso SDT Invocación de Objetos Dominios Enumerados Master Pages PXPatterns PX Work With PX Parameter Request PX Composer ¿Qué es un Patrón? Comportamiento común entre objetos (programación) Variables que diferencian distintos objetos generados ¿Qué es GeneXus Patterns? Herramienta que permite representar un Patrón Variables que definen al objeto final crean la “instancia” La estructura de la instancia es un grafo Una macro definición valida la estructura del grafo Existen opciones comunes para las distintas instancias Utilización de GeneXus Patterns Herramienta de Desarrollo Selector de Patterns. Selector de Kbs. Barra Izquierda Área central Barra Derecha Barra Inferior Configuración inicial Instancia de PX Work With Transacción Principal Level Navegación del Work With Selección View Tabs Página 2 de 50 UBICACIÓN Pg. V 1 00:00:00 4 V 1 00:00:25 4 V 1 00:02:02 4 V 1 00:25:15 13 V 1 00:27:08 14 V 1 00:31:04 16 V 1 00:36:20 18 V 1 00:37:09 18 V 1 00:42:20 19 V 1 00:43:38 20 V 1 00:48:44 22 V 1 00:49:00 22 V 1 00:49:45 22 V 1 00:50:23 22 V 1 00:50:29 22 V 1 00:50:52 22 V 1 00:51:26 22 V 1 00:51:34 23 V 1 00:52:45 23 V 1 00:53:37 23 V 1 00:53:45 23 V 1 00:54:03 24 V 1 00:54:33 25 V 1 00:55:29 25 V 1 00:58:42 26 V 1 00:58:48 27 V 1 00:59:22 27 V 1 01:00:15 28 V 1 01:06:24 30 V 1 01:06:38 30 V 1 01:06:57 31 V 1 01:09:05 31 V 1 01:09:48 31 V 1 01:13:26 33 V 1 01:13:31 34 TEMA Selection del WorkWith Attributes Modes Orders Filter Parameters Actions Variables Fixed Data Página 3 de 50 UBICACIÓN V1 V1 V1 V1 V1 V1 V1 V1 V1 01:20:57 01:24:29 01:29:30 01:36:58 01:41:34 01:48:55 01:55:50 01:59:28 02:02:12 Pg. 35 37 38 40 41 45 46 48 49 PuntoExe Tools Conceptos Previos al Curso V1 00:00:25 Vamos a repasar algunos conceptos de la versión GX 9.0 (algunos venían de la 8.0) que son necesarios y se van a manejar mucho trabajando con Patterns. SDT V1 00:02:02 SDT (Structured Data Types) es una forma de manejar elementos estructurados complejos. Se trata de poder declarar en variables elementos estructurados complejos para después manipular. Estructuras Vamos a definir un estructurado y ver como se representa. Comenzamos por abrir un SDT que ya van a tener que utilizar: Acá tenemos un SDT que se llama Context, que está definiendo es una estructura bien parecida a la de una transacción, donde se define un elemento de un nivel y debajo, campos. A nivel del SDT serían propiedades del SDT donde uno define el dato y el tipo de dato al cual está asociado (Atributo, Dominio o tipo de dato definido con el DataType de GeneXus). Si después abrimos cualquier Objeto, vamos a los Eventos, definimos una Variable Context y vamos a la parte de DataType. Allí vamos a encontrar un apartado de “Structures” (debajo de los de DataTypes y Extended DataTypes) donde aparecen todas las estructuras que se hayan definido en la sección de SDTs. Página 4 de 50 En el sexto lugar se encuentra el “Context” que queremos asociar a esta variable. Después en cualquier lugar, si llamamos a esta variable: y ponemos el punto, podremos trabajar sobre las propiedades establecidas en el SDT (UsuCod, UsuNom). Colecciones Colecciones son un conjunto de Estructuras. Las Colecciones se pueden manejar de distintas maneras. Vamos a crear un nuevo SDT para empezar a manejar Colecciones: Página 5 de 50 con dos propiedades (datos) numéricos de 4 y una tercera también numérico de 4, pero en la columna “Collection” seleccionamos “True”, lo que indica que en realidad va a ser una Colección de numéricos de 4. Vamos a ver que también pueden definirse propiedades que a su vez sean estructurados (SDTs). Por ejemplo, podríamos definir que Pro1: sea de tipo Context y entonces deberíamos referirnos a Pro1.UsuNom para invocar esa propiedad del Context. Esto también aplica para las colecciones, que es lo que más interesa, para que podamos definir colecciones de datos estructurados y tener muchos datos acumulados uno al lado del otro. La que acabamos de ver es una forma de definir una colección basada en una variable y para referirnos a ella tenemos que poner Prueba2.ColProp3. Existe otra forma de definir colecciones que es no definirla a nivel de una propiedad (colProp3) sino hacerlo a nivel del propio estructurado (Prueba2) y lo que estoy determinando es que todo el estructurado va a estar metido dentro de una colección. Página 6 de 50 Y ven que en la columna “Item Name” se definió automáticamente un nombre (Prueba2Item). Esto, porque cuando trabajamos con una colección hay dos conceptos en juego: Uno es la colección y otro es el elemento de la colección. El ItemName es una propiedad necesaria para poder trabajar con estos dos conceptos. Prueba2 representa la colección y Prueba2Item representa al elemento de la colección. Este elemento en realidad es un estructurado que tiene las tres propiedades: Pro1, Pro2 y ColProp3. En el caso anterior, si ColProp3 hubiera sido una colección basada en el estructurado Context: seguirían estando en juego los dos conceptos: El que representa a la colección que es la variable basada en Prueba2.ColProp3 y el elemento es el propio SDT que definimos en este caso que es Context. Ahora GeneXus no necesita agregar el identificador por defecto del elemento porque el mismo ya fue definido por nosotros con anterioridad (Context). Vamos ahora a crear un Web Panel al que llamamos Prueba e ir al evento Start para referenciar al SDT (Prueba2) que acabamos de crear. Si creamos una variable &Prueba2 basada en este estructurado y escribimos &Prueba2 y ponemos el punto: Página 7 de 50 aparecen las tres propiedades: Pro1, Pro2, y ColProp3. Y tal como ocurre cuando trabajamos con programación orientada a objetos, también se proponen los métodos que hayan sido definidos para este estructurado. El SDT no tiene métodos definidos por el usuario (no es una “clase” conceptualmente), pero sí tiene métodos predefinidos por GeneXus. Tiene el método Clone para clonar colecciones o variables basadas en estructurados, tiene el FromXML y el ToXML para cuando estamos trabajando con una estructura simple y sirven para grabar XML y para recuperar de un XML. Si seleccionamos ColProp3 y ponemos &Prueba2.ColProp3 y ponemos el punto, en el caso de las colecciones aparecen más métodos asociados a esta la misma. Uno es Clear para limpiar la colección, Clone, FromXML y ToXML son los que ya vimos y después tenemos el Sort para ordenar la colección, el Item Página 8 de 50 para referenciar la posición dentro de la colección (como el subíndice de un array) y el IndexOf es al revés: Dado un elemento, determinar si está metido dentro de la colección. Hay que tener cuidado con este indexOf porque no siempre funciona. Después tenemos las propiedades: Count para averiguar la cantidad de elementos y CourrentItem para saber donde estamos posicionados. Lo que vamos a hacer ahora es recorrer un estructurado. Volviendo al evento Start del Web Panel “Prueba”, si programamos: en cada paso estamos instanciando un elemento dentro de la colección Prueba2.ColProp3. En este caso, dentro del For, tenemos la iteración de cada uno de los elementos de la colección y podemos trabajar con la variable &Context que se instanció en el For y referirnos a cualquiera de las propiedades definidas en el enumerado. También existe otra manera de recorrer el estructurado que es manejando el método Ítem, para lo cual habría que declarar una variable numérica (una del tipo &Index) y sustituir el For por un Do While. De este modo la rutina quedaría así: Página 9 de 50 Si el estructurado hubiera sido una colección en sí misma (del segundo tipo que vimos): Entonces &Prueba2 es directamente la colección y la propiedad Count habría saltado al poner el punto como vamos a ver a continuación: Ahora bien, para instanciar un elemento deberíamos haber declarado una nueva variable &Elemento basada en el nombre asignado por defecto a Ítems de esta colección (Prueba2.Prueba2Item), que pueda referenciar a las propiedades de este elemento de la colección. Esto es precisamente lo que vamos a hacer ahora: Definir la variable &Elemento para poder referir los elementos de esta colección. Página 10 de 50 y ahora sí, al poner el punto a la variable &Elemento, van a aparecer las propiedades Pro1, Pro2 y Prop3 del estructurado: Luego para almacenar es fácil. Supongamos que estamos recorriendo una tabla con un For Each y en determinado momento estamos en condiciones de agregar un nuevo elemento a la colección. La rutina para hacerlo sería algo así: Página 11 de 50 Para entender el proceso debemos imaginar la colección como una sucesión de punteros que apuntan a diferentes lugares de memoria. 10:21:21 Lo primero será solicitar un nuevo lugar de memoria para alojar los datos del nuevo elemento de la colección al que va a apuntar la variable. Esto es lo que hacemos con la asignación &Elemento = New Prueba2.Prueba2Item (): 10:21:48 y al ejecutar &Prueba2.Add(&Elemento), estamos agregando este nuevo puntero a la colección: 10:22:04 Si hubiéramos omitido hacer el New, por más que hayamos cambiado las propiedades del elemento, el nuevo puntero le seguiría apuntando a la dirección de memoria anterior: 10:22:25 Página 12 de 50 Esto tiene ventajas y desventajas. La desventaja es que tenemos que hacer el New en una iteración. Y ojo, que si no lo hacemos no va a saltar un error de tipo alguno. La gran ventaja es que, como se están manejando punteros, podemos pasar por parámetros tanto la colección como el elemento y en realidad lo que estamos pasando es el puntero. Adentro podemos estar modificando las propiedades de la colección sin tener que hacer la devolución del elemento, simplemente porque en realidad lo que se pasó fue el puntero. Si una subrutina o un procedimiento que estemos invocando o subinvocando, grabó algo dentro de la colección, la misma quedará modificada y no será necesario devolver los nuevos datos porque lo que quedó modificada es una sección de memoria. Invocación de Objetos V1 00:25:15 Vamos a abrir un Web Panel: aquí estamos viendo la vieja forma de invocar con un comando link a un Web Panel. Existe otra forma de hacer las invocaciones, que es: Primero identificar al Objeto GeneXus (HHome) y después poner punto: y seleccionar el método Link(). Página 13 de 50 Si tuviéramos más parámetros y en la vieja forma fuera algo de este estilo: Home.Link = Link(HHome ,&parm1), en la nueva forma sería: ya no queda el objeto invocado dentro de la función Link, sino que identifico el objeto, punto Link y después se ponen los parámetros requeridos. Esto en los Patterns lo vamos a ver muy a menudo porque en su mayoría están trabajando con esta nueva lógica. Si ven además los Patterns de GeneXus, tienen una que se llama WorkWith y otro que se llama WorkWith 8.0 y precisamente los diferencia la forma de invocar a los objetos: El WorkWith 8.0, por razones de compatibilidad, todavía utiliza la vieja forma de invocar objetos. Dominios Enumerados V1 00:27:08 La propiedad que refiere a los Dominios Enumerados (que creo que es de la 9.0) es la posibilidad de incorporar para un dominio (basado en un tipo de dato o en otro dominio, como siempre), en su definición: Página 14 de 50 esta nueva propiedad que se llama Enum values y que permite predefinir valores enumerados de ese dominio. Por ejemplo, en un dominio para valores numéricos booleanos que llamaremos “Boolean”, con esta propiedad podemos predefinir: los valores a los que podremos denominar “True” (para el 1) y “False” (para el 0). Entonces cuando manejemos variables basadas en el dominio booliano, por ejemplo la variable &Ok, podremos preguntar por ella en forma muy intuitiva en una rutina del tipo: en la que, haciendo referencia al dominio “Boolean” y poner el punto, GeneXus automáticamente muestra las propiedades “True” y “False” que fueron enumeradas para este dominio. Además el programa nos va a quedar mucho mejor documentado y si mañana decidimos que el “True” sea 2 en lugar de 1, bastará corregir la definición del enumerado, sin necesidad de cambiar la lógica de estas rutinas. Página 15 de 50 Master Pages V1 00:31:04 La Master Page es una funcionalidad que vino con la 9.0 que provee la facilidad de resolver lo que antiguamente había que programar “a mano” en los Web Panels para representar al Menú y otros elementos del entorno. Entonces, para representarlo se armaba una estructura en el Web Panel para poner un componente que fuera el Menú y éste siempre se llamaba de la misma manera. Pero era necesario programar en cada Web Panel la lógica de invocar al componente. Para quienes no han trabajado en Web, el objetivo de la Master Page es muy parecido a la función del Style Area de un ambiente Win. Básicamente lo que se programa es el entorno de navegación de una Data Area principal. Se declara una Master Page para definir el entorno, de modo que hay que definir toda la pantalla y decir donde está el Data Area, que ahora se llama Content Placeholder. En este caso tenemos un Header (Web Component cmpHeader), una barra izquierda (Web Component cmpMenu), un Footer (Web Component cmpScripts) y el Título (Área de Contenidos). Inclusive el Título no está en cada uno de los Web Panels, el Título está afuera, en la Master Page. La forma de insertar este Content Placeholder es mediante la propiedad “Content Placeholder”, a la que podemos acceder cuando estamos en la Master Page presionando el menú Insert. Página 16 de 50 Esta propiedad sólo está disponible en los objetos Web Panels de tipo Master Pages. Para declarar una Master Page, desde cualquier Web Panel es posible seleccionar la propiedad “Type” y asignarle el valor Master Page: Por otro lado, entre las propiedades de cualquier Web Panel se encuentra la “Master Page”, que no está visible en los que son tipo Master Page y con la que se selecciona cuál de las Master Pages declaradas va a contenerlo: Página 17 de 50 En los casos de migración Win a Web que hemos asistido no fue necesario declarar más que una Master Page, pero en las primeras versiones de las PXTools, por ejemplo, teníamos una Master Page asociada al Prompt, que por su particular comportamiento (ventana más chica, sin menús y con una estética sencilla) justificaba una nueva Master Page. En las versiones posteriores se pudo resolver este comportamiento especial con una única Master Page. PXPatterns V1 00:36:20 Ahora vamos a profundizar en los Patterns de PuntoExe que integran las PXTools. Hasta el momento contamos con tres patrones que han podido resolver los requerimientos de nuestros más exigentes clientes, pero siempre hacemos la salvedad que todo esto es muy dinámico y cada nuevo proyecto puede generar la necesidad de desarrollar un nuevo patrón. Estos patrones fueron desarrollados con el objetivo de minimizar el impacto que el pasaje a un ambiente web tiene, a nivel de la interfaz de usuario, en relación con el ambiente Win. No debemos olvidar que para el usuario, el operar un sistema desde un navegador ya es todo un cambio. PX Work With V1 00:37:09 El PXWorkWith es básicamente el WorkWith de GeneXus pero mucho más potenciado en cuanto a sus funcionalidades y con una visión bastante diferente en cuanto a su misión dentro de un proyecto de desarrollo web, como vimos en la introducción. Con este patrón se programan distintas cosas, pero lo principal, como su nombre lo dice es resolver el “Trabajar Con” una entidad cuyos registros se muestran en una Grilla. Desde el punto de vista del comportamiento gráfico de sus pantallas en tiempo de operación, lo más destacable es que este patrón logra que todas sus prestaciones se resuelvan dentro de un entorno que mantiene estable la imagen corporativa de la aplicación. Dicho de otro modo, logra mantener siempre visibles todos los elementos que se declaran en la Master Page (Cabezal, Barra Izquierda, Barra Derecha si existe y Pié de Página). Página 18 de 50 En el WorkWith original, si la Grilla es muy ancha, o tiene muchos registros, se genera un scroll horizontal o vertical general de pantalla que involucra a todos los componentes del entorno. Esto nunca va a ocurrir en los Web Panels generados con el patrón PXWorkWith porque el scrolling es local a la Grilla y todos los demás componentes de la pantalla (incluyendo los filtros del propio Web Panel) permanecen activos durante todo su recorrido. Es un comportamiento muy similar al de una aplicación Win, aunque algunos cambios son inevitables por tratarse del medio Web. Por ejemplo, la Grilla necesita de todos modos los botones de paginación que se muestran arriba a la izquierda. No olvidemos que esto es HTML y no podemos desplegar una Grilla con miles de tuplas porque la carga de la pantalla demoraría horas, pero sí podemos balancear un número razonable de registros escroleables con el saludable recurso de la paginación del resto de su contenido. Este número razonable de registros depende de la conectividad de la red, por eso en las PXTools esta cantidad es configurable y oscila entre los 50 y 200 registros en una intranet común. PX Parameter Request V1 00:42:20 Originalmente, el Parameter Request fue un patrón diseñado para programar aquellas pantallas en las que se piden datos al operador para después llamar a otro objeto (Reportes o Procedimientos). Sirve entonces para instanciar los parámetros que deben ser pasados para solicitar otro objeto. Página 19 de 50 en este caso la pantalla solicita datos para llamar a un Reporte, pero podría llamar a otro Web Panel o a un Procedimiento. Después vamos a ver que también usamos este patrón para programar pantallas que muestren datos en este formato tabular, en donde las variables pueden o no, ser editables. PX Composer V1 00:43:38 Este patrón fue desarrollado para resolver los requerimientos de un proyecto en el cual las pantallas a programar eran extremadamente complejas: Página 20 de 50 Cuando analizamos como resolverlas vimos que la solución no podía pasar por darles más funcionalidades a los dos patrones que habíamos desarrollado hasta ese momento. Entonces surgió la idea de desarrollar un nuevo patrón que permitiera “componer” la pantalla a partir de secciones de la misma que constituían una unidad lógica, aunque estuvieran interactuando con otras secciones. Así nació el PXComposer, que es un patrón muy sencillo porque lo único que hace es integrar elementos que fueron componentizados. De este modo, la pantalla anterior en su versión web luce así: Algunos datos fueron quitados, a solicitud del cliente, para la versión web, pero arriba podemos ver la sección “Póliza”, al medio a la izquierda la sección “Movimiento”, al medio a la derecha la sección de “Cobranza” (no se quisieron mostrar las Comisiones), abajo a la izquierda la Grilla y a su derecha un texto ampliatorio que en este caso está vacío. Si desestructuramos esta pantalla, lo que tenemos son cuatro Parameter Request y un WorkWith que se distribuyen así: PX Parameter Request Página 21 de 50 PX Parameter Request PX Parameter Request ======= Grilla ======== PX WorkWith PX Parameter Request Conceptualmente, dentro de GeneXus, el PXComposer es un patrón que genera un Web Panel que invoca otros Web Panels como componentes. ¿Qué es un Patrón? V1 00:48:44 Ahora vamos a empezar a trabajar con patrones y la primer pregunta que cabe es: ¿Qué es un Patrón? Comportamiento común entre objetos (programación) V1 00:49:00 Se desarrolla un patrón cuando se detecta un comportamiento común entre un conjunto de objetos. Esta coincidencia está determinando un “patrón” de comportamiento y los Patterns logran sistematizar su programación. Un caso muy claro es el WorkWith, que resuelve siempre de manera similar el “Trabajar Con” entidades del sistema. Y el Pattern WorkWith procura evitar que el programador tenga que repetir en cada objeto las secciones de código que implementan este comportamiento. Variables que diferencian los distintos objetos generados V1 00:49:45 Vamos a ver que detrás del patrón están las “instancias” que permiten invocar al patrón con las particularidades del objeto que vamos a desarrollar. Para programar el “Trabajar Con Países” debemos llamar al patrón WorkWith “instanciando” la Transacción de Países. ¿Qué es GeneXus Patterns? V1 00:50:23 Para poder aplicar esta tecnología a nivel de GeneXus fue necesario que Artech proveyera los instrumentos de infraestructura que permitieran su desarrollo compatible. Herramienta que permite representar un Patrón V1 00:50:29 Esta herramienta nos da el marco para trabajar con patrones. Artech armó una plataforma para aplicar patrones, para ejecutar patrones y para programar patrones. Esta última facilidad refiere al Development de desarrollo de un patrón. Las variables que definen al objeto final crean la “instancia” V1 00:50:52 Cuando programamos una Instancia de un patrón, estamos determinando el comportamiento específico de uno o más objetos GeneXus que puede generar ese patrón. La estructura de la instancia es un grafo V1 00:51:26 La forma de representar las instancias es, vamos a verlo ahora, a través de un grafo. Página 22 de 50 Una macro definición valida la estructura del grafo V1 00:51:34 Existe una macro definición que valida la estructura de este grafo. Sobre esta macro definición trabajamos en PuntoExe, desarrollando nuevos patrones o mejorando las funcionalidades de los que ya hemos desarrollado. Vamos a abrir una Instancia. El grafo tiene una estructura arbórea (área central de la figura siguiente): y cuando estamos ubicados en un nodo y aplicamos botón derecho, el editor nos muestra los nodos que fueron previstos por el desarrollador del patrón para agregar como subnodos del anterior, en esta instancia. Existen opciones comunes para las distintas instancias V1 00:52:45 A nivel de cada patrón existe un “Config” donde se pueden determinar comportamientos comunes a todos los objetos generados con las Instancias de ese patrón. Por ejemplo, para el patrón WorkWith, que los botones de paginación de todas las grillas estén arriba a la izquierda o en algún otro lugar de la pantalla que haya sido previsto por el desarrollador del patrón. Utilización de GeneXus Patterns V1 00:53:37 GeneXus Patterns es una plataforma de desarrollo y como tal cuenta con una serie de entidades e instrumentos, algunos de interés para el desarrollador de patrones (caso de PuntoExe) y otros de interés para el desarrollador con patrones (caso de ustedes). En este curso nos vamos a ocupar del segundo grupo. Herramienta de Desarrollo V1 00:53:45 Ustedes van a usar el editor para programar instancias de GeneXus Patterns como herramienta de desarrollo y en la figura siguiente se muestra un Screenshot de la pantalla de acceso al sistema. La idea es ir describiendo cada una de sus secciones y viendo las funcionalidades que se ofrecen en ellas: Página 23 de 50 Selector de Kbs. V1 00:54:33 Lo primero que encontramos en la barra superior es el Selector de KBs: para seleccionar sobre qué KB se va a trabajar. Al presionar este botón se abre el Browse Folder y allí se selecciona la raíz de la KB requerida. Página 24 de 50 Selector de Patterns. V1 00:55:21 A la derecha de la barra superior se encuentra el Selector de Patrones: que mediante una combo muestra los patrones instalados en el sistema para que podamos seleccionar el que requerimos para nuestro desarrollo. Barra Izquierda La barra izquierda sirve para dos funciones: Página 25 de 50 V1 00:55:29 En la barra inferior tenemos dos tabs: A la izquierda el Selector de Objetos de la KB y a la derecha el Selector de las Instancias generadas (al principio el contenido va a estar vacío). Estas Instancias son archivos XML grabados en disco, en una carpeta que vamos a ver bien donde queda y en la versión Rocha de GeneXus van a estar metidos dentro de la KB. Por ahora, en la 9.0 se encuentran en un directorio que se crea dentro de la KB de GeneXus. ¿Por qué necesitamos un acceso a los Objetos de la KB (en particular a las Transacciones de la KB son las que se muestran por defecto) con el primer Tab? Porque el objetivo inicial de Artech con esta metodología fue permitir desarrollar patrones que a partir de una Transacción pudieran automatizar los comportamientos más comunes con estas entidades. Caso típico el WorkWith. En términos generales, el objetivo de este patrón justamente es permitir que haciendo doble clic en la Transacción, inmediatamente se arme una instancia por defecto de WorkWith basada en esa Transacción. Habiendo logrado superar ampliamente este objetivo inicial, en los otros dos patrones que hemos desarrollado nosotros hasta ahora y seguramente en los que vamos a desarrollar en el futuro, esta funcionalidad no se cumple. Área central V1 00:58:42 En el área central se visualizan los nodos del árbol de la instancia: área sobre cuyas características ya hemos hablado. Página 26 de 50 Barra Derecha V1 00:58:48 En la barra derecha se muestran las propiedades del nodo seleccionado del árbol en la barra central: Ahora vamos a empezar a profundizar en lo que representa cada nodo y vamos a ver cómo mediante estas propiedades podemos lograr desarrollar objetos GeneXus que cumplan con los requerimientos de la interfaz de usuario web de los sistemas sobre los que ustedes van a trabajar. Barra Inferior V1 00:59:22 La barra inferior tiene el log de salida, que es autohidden (se oculta automáticamente) y es para cuando empezamos a aplicar la parte declarativa y a pedir al sistema la generación los objetos GeneXus a partir de la Instancia. En esta barra aparece el Log con la información que se va generando y en el caso de las PXTools, también pueden ir apareciendo los warnings del sistema por inconsistencias detectadas durante la generación. Página 27 de 50 Configuración inicial V1 01:00:15 Cuando abren una KB que nunca fue abierta con Patterns, se les abre esta pantalla: Página 28 de 50 que está pidiendo resolver la configuración para la interrelación del development del patrón con la KB de GeneXus. En la primer combo “Model” se define sobre qué modelo se va a generar. En la segunda “Apply and Consolidate”, qué tipo de impacto, en relación con la KB se va a solicitar (recuerden que en la 9.0 los patrones lo que hacen es armar XPZs que son archivos de distribución de GeneXus), pues al usar GXPublic para procesar estos archivos, las opciones que ofrece esta combo son las funciones que provee GXPublic. Aquí se indica si se requiere sólo consolidar todos los objetos, impactar el modelo, impactar y especificar, especificar y ya compilar o compilar y ejecutar además. Nosotros por lo general estas últimas dos opciones nunca las pedimos porque trabajamos con KBs muy grandes y como a medida que programamos se crean muchos objetos Main, el proceso de compilación llevaría mucho tiempo. Por eso llegamos hasta la especificación, luego entramos al Main principal y pedimos compilar ese Main, pues el Compile que figura en la combo va a pedir la compilación de todos los Main que se hayan generado. Hasta ahora nosotros hemos trabajado mayoritariamente en Java y el proceso de compilación en Java genera un MAC donde se establecen las interdependencias entre los objetos y a pesar de que ya esté compilado un objeto, si pedimos compilarlo nuevamente demora, porque se va a controlar que todas las dependencias de ese objeto hayan sido compiladas. En la tercera “GeneXus Version”, GeneXus detecta la versión de la KB con que se está trabajando. En la cuarta “Build Action” nosotros siempre cambiamos la opción que viene por defecto: “Build Pending (updated since last specification)” que es para especificar todo lo que hay pendiente desde la última especificación que se hubiera hecho, por la opción: “Specify Consolidated Objects” que está mucho más orientada al trabajo con Patterns y es para especificar todos los objetos que se consolidaron, los que incorporó el patrón a partir de los archivos de distribución XPZ. En la quinta “Specification” que ofrece las opciones de especificación de GeneXus: “Full Spacification” que viene por defecto, “Check Specification” que es la que elegimos normalmente y “Force Generation”. Respecto a las siguientes Check Boxes, la primera “Aumatically execute database reorganization” nunca la seleccionamos, porque al haber optado por “Impact, Specify” en Apply Pattern, para que pase de Diseño al Modelo indicado y si trabajando sobre la KB de Diseño, hacemos algún cambio a nivel de atributos o de tablas que requiera un impacto, tratamos de que no lo haga el pattern sino de hacerlo más controladamente nosotros “a mano”. La siguiente Check Box: “Stop import on specification errors” sí, la cliqueamos y la de abajo: “Stop import on specification warnings” también (aunque por defecto no viene cliqueada), para que nos avise para detectarlos aunque se trate de warnings. Por lo general van a salir warnings si uno declara variables y no las define u otro tipo de errores por el estilo que resuelve el propio GeneXus, pero somos estrictos en tratar que los objetos generados no tengan ningún warning, entonces recomendamos cliquear las dos e ir tratando de solucionar cualquier tipo de error. Por último el Run Command es para indicar la URL del ejecutable si se solicitó compilar y ejecutar en “Apply and Consolidate”. Página 29 de 50 Si ponen “Cancel” en esta primera pantalla, entonces esta nueva KB no les va a quedar seleccionada. Instancia de PX Work With V1 01:06:24 Ahora vamos a empezar a profundizar en el Pttern WorkWith y en principio vamos a ver los nodos más tradicionales del patrón. Vimos que originalmente este patrón se diseñó para trabajar con una Transacción. Se trata del “Trabajar Con” una entidad del sistema que es una Transacción. Transacción Principal V1 01:06:38 Por ejemplo, si cliqueamos dos veces sobre la Transacción “Clientes”: Entonces, el WorkWith se compone básicamente del Nodo Transaction y del Nodo Level. Son los dos elementos principales. A esto, que es lo que genera por defecto el patrón cuando seleccionamos una Transacción, vamos a poder agregarle más cosas. Por ejemplo, (botón derecho del mouse sobre el nodo Instance) podemos agregar un segundo Nodo Level. Esto quiere decir: Otro “Trabajar Con” (distinto) de la misma Transacción. Si llegáramos a salvar esta instancia que se creó por defecto, le estaríamos pasando por arriba a la instancia de Trabajar Con Clientes que ya existe en esta KB. Esto, si mantuviéramos el mismo nombre de la lengüeta de la barra superior, donde se ven los nombres de las instancias que tenemos abiertas. Para evitarlo tenemos la opción Save As en el menú superior: Página 30 de 50 que nos permite salvarla con otro nombre, aunque no es habitual hacerlo. Lo normal es volver a abrir la instancia que tenemos salvada accediendo a ella por el Selector de las Instancias generadas (Tab derecho de la Barra Izquierda). Level V1 01:06:57 Vamos a ver ahora los nodos principales del Nodo Level: El Selection (que es propiamente el WorkWith), el View, el Prompt y el Description Atribute. Estos nodos ya estaban presentes en el WorkWith original de GeneXus. Navegación del Work With V1 01:09:05 Ahora vamos a profundizar en cada uno de estos nodos. Selection V1 01:09:48 Ya dijimos que el nodo Selection es el objeto “Trabajar Con” de GeneXus y uno de los cambios fuertes que hicimos es en cuanto a la nomenclatura de los objetos que se generan. El nodo que comanda el nombre de los objetos a generar es el Level, y es importante que declaren la propiedad Name: Página 31 de 50 por defecto el Name va a quedar con el nombre de la Transacción. Nosotros tratamos de usar una nomenclatura según la cual se trata de abreviar a tres caracteres los nombres de los objetos, seguidos de un numerador secuencial de dos dígitos. Es recomendable incluir este numerador, pues nunca se sabe si mañana vamos a tener que programar un segundo “Trabajar Con” para esta Transacción, cuyo nombre se diferenciará con este secuencial. En este caso le llamamos “Cli01” y todos los elementos que se generen debajo de este Level van a nominarse con una referencia a ese nombre. Cada uno de los nodos y subnodos debajo de él van a tener prefijos que los relacionen. En esto cambiamos bastante el criterio que tenía el WorkWith original de Artech, que a nuestro juicio generaba nombres extremadamente largos que dificultaban el uso de nuestros manejadores de KBs. La forma de administrar estos prefijos se establece en el archivo de configuración, al que se accede por el menú Tools: y vamos a “Change Default Pattern Configuration” que en una sección “Prefixs” define por defecto (pero podemos cambiar) los prefijos asociados a cada entidad vamos a manejar: En el caso del Selection, le va a poner un “Tr” seguido del nombre del Level. Donde dice <Object> en realidad va el nombre del Level. Al nodo View le va a poner un prefijo “Ve” (de Ver), al Query “Cs” (de Consulta), al Prompt “Pr” (de Prompt), al Tabular “Tb” (de Tab), en fin, cada tipo de objeto generado va a tener su prefijo. Entonces, volviendo al ejemplo: Página 32 de 50 el objeto generado por el nodo Selection será el TrCli01, el generado por el View será el VeCli01 y debajo de él, a los nombres de los nodos Tabs se le agrega un correlativo que defina la posición del Tab. El Tab General será el TbCli0101, el de Direcciones TbCli0102, el de Contactos TbCli0103, etc. Si agrego o cambio la posición de los Tabs sus nombres se van regenerar de modo que siempre representen el orden en que se van a mostrar. Ahora vamos a ver, en tiempo de ejecución del programa, cual es el comportamiento funcional de los objetos generados por estos nodos: En el WorkWith tenemos básicamente el Selection, que es éste que estamos viendo, la Transacción, que vamos a ver si hacemos Insert ( ), update( ) o delete( ) (estos últimos a nivel de cada registro), pero además tenemos la posibilidad de pasar al View de cada registro si hacemos clic sobre el Description Attribute ( , para el primero) que hayamos definido a nivel de la Transacción (la 9.0 permite esta declaración). View V1 01:13:26 Este View es una especie de visualización ampliada del registro seleccionado. Página 33 de 50 Tabs Entonces, haciendo clic en V1 01:13:31 pasamos a esta otra pantalla: en la cual podemos ver el Tab General que cumple una función similar a la Transacción en Modo Display (pero no es la Transacción en Modo Display) y luego los siguientes Tabs (Capítulos, Rubros y Diferencia de Cambio) que son accesos a elementos subordinados o a elementos relacionados con ese registro. En este caso, por ejemplo, que estamos accediendo contablemente a un Tipo de Plan de Cuentas, debajo de él vemos los Rubros de éste: Cuando trabajamos en plataforma Win, para el operador es muy rápido trabajar con elementos subordinados: Apretamos un botón y accedemos a un hijo, apretamos “Escape”, salimos de la pantalla, apretamos otro botón y accedemos a otro hijo. Es bastante rápido trabajar con este tipo de relaciones entre padres, hijos y hermanos. Página 34 de 50 Esto puede ser así porque en Win, cuando ponemos “Escape”, se nos cerró la ventana y nos quedó la de abajo y toda la cadena de accesos está controlada por el Sistema Operativo. En Web esto es mucho más costoso, porque cuando pasamos a nueva pantalla, la anterior se fue y me quedó la pantalla del hijo, entonces si tenemos que retornar al padre debemos volver a cargarlo nuevamente. Esto implica un nuevo acceso a la Base de Datos para volver a desplegar la pantalla del padre simplemente para después ir a otro hijo. Esto se solucionó con esta modalidad de uso de Tabs. Para acceder a elementos hijos de una entidad, accedo a lo que se llama el View y en él puedo pasar entre Tabs a los elementos hijos sin tener que volver al padre. Para este mismo caso, en Win, en algún lugar de la propia pantalla anterior (WorkWith de la figura 11:14:59) seguramente tendríamos los botones de Capítulos, Rubros y Diferencia de Cambio para pasar a ver estos elementos subordinados. Y éste es precisamente uno de los cambios que en el pasaje a una versión Web debemos hacer por requerimientos de esta nueva plataforma. Por ejemplo, todas aquellas pantallas intermedias que son comunes en Win para solicitar algún dato previo, también hay que tratar de eliminarlas y pedir el dato en la pantalla anterior. Estamos trabajando con HTML y tiene un costo bastante mayor abrir pantallas Web que abrir pantallas Win. Entonces, esta metodología que implementa la lógica relación entre el Selection, el View y los Tabs y ya venía con el WorkWith original, nosotros la mantuvimos por entender mejoraba los tiempos de operación del sistema. Después tenemos el nodo Prompt, pero está totalmente descolgado de toda esta lógica. Si bien depende de la Transacción, no sirve para este WorkWith sino para otro WorkWith que esté llamando a otra Transacción pero deba hacer un Prompt, en este caso, de Clientes. Uno diseña en el WorkWith de la Transacción de Clientes el Trabajar Con Clientes y el Prompt de Clientes, pero no es un objeto directamente relacionado con el Selection, ni con el View ni con los Tabs. La idea es que, todo lo que esté relacionado con la Transacción de Clientes se diseñe en esta Instancia. Por eso como vimos al entrar en la Transacción Principal del ejemplo (V 1 | 01:06:38), es posible agregar otro Level, es decir, otro “Trabajar Con” (distinto) de la misma Transacción para que todos los WorkWith de esta Transacción queden en la misma Instancia. Esto optimiza además el trabajo de programación cuando se trabaja con sistemas muy grandes, pues concentra en una sola Instancia todo lo relativo a esa Transacción. Entonces, como metodología es recomendable que todos los “Trabajar Con” relativos a una entidad estén definidos en la misma Instancia. Sólo en caso de que se trate de un subsistema cuya lógica es muy particular y entonces queramos independizar la Instancia, por ejemplo: “Seguridad de Clientes” con una lógica muy distinta del resto, es aceptable crear una nueva Instancia para la misma Transacción. Selection del WorkWith V1 01:20:57 Vamos a entrar en profundidad con el Selection viendo las propiedades más importantes de este nodo. Página 35 de 50 Comencemos por recordar que el nodo Level tiene el Description Attribute, que se va a cargar por defecto del Description Attribute que se haya declarado en la Transacción: Por defecto en la 9.0, cuando se declara una Transacción, automáticamente se va a asignar el ícono de Description Attribute (una lupa) a un atributo al que hayamos incluido en su nombre algo como Nombre, Nom, o similar. Posteriormente podemos cambiar esta declaración apretando botón derecho del mouse sobre otro atributo y seleccionando “Set as description attribute”. Esta declaración sólo sirve a los efectos que estamos viendo, de crear un hipervínculo sobre ese atributo en la Grilla del “Trabajar Con”, para pasar al en el ejemplo View del Selection, como vimos que ocurría con anterior. Como habrán notado, yo tengo que estar continuamente cerrando la KB y abriendo el Pattern. Esto es una limitante que tenemos en la 9.0 que consiste en que, si trabajamos con Pattern en una KB, la KB la tengo en modo Diseño, entonces no puedo estar abriéndola a la vez ni desde otro lugar ni desde mi misma sesión en Diseño. Ahora sí, aquí vemos la instancia correspondiente: y vemos el Description Attribute definido por defecto en la Transaction. Página 36 de 50 Pero desde esta misma instancia lo puedo cambiar también, abriendo la combo de la propiedad Name y seleccionando otro atributo de la transacción. El que cambiemos este valor a nivel de este Level no cambia el valor por defecto declarado en la Transacción. Entonces, el Description Attribute va a relacionar el nodo Selection (abajo) con el View (más abajo), por lo que tiene que tratarse de un atributo que esté en la Grilla del “Trabajar Con”. De modo que debe estar dentro del nodo Attribute que es donde se declaran los elementos que están dentro de la Grilla: Attributes V1 01:24:29 Al nodo Attribute lo vamos a encontrar en muchos lados de la instancia y dependiendo de bajo qué nodo esté representa cosas distintas. En este caso, dentro del Selection, representa las Columnas de la Grilla. En cambio debajo del nodo Form de la Transacción, contiene los atributos que están dentro del Form de la Transacción. Este nodo Form no se carga por defecto pues no hay manera de saber como se va a diseñar el mismo. Página 37 de 50 Si no se agrega este nodo, el patrón va a hacer por defecto lo mismo que hacía el WorkWith original, que es generar el Form de la Transacción a partir de toda la estructura de la transacción, lo que tiene sus inconvenientes porque va a mostrar en el Form atributos que son internos, no para mostrar. Por defecto sí, se van a cargar todos los atributos de la Transacción en el nodo Attribute y tendremos que eliminar los que no correspondan (Supr en el atributo seleccionado). Para agregar nuevamente un atributo que hayamos eliminado tenemos dos maneras: 1. Botón derecho sobre el nodo Attribute y opción Select Attribute y te abre una ventana que te va a posicionar en la Transacción con todos sus atributos donde podremos volver a seleccionar el eliminado por error. 2. Botón derecho sobre el nodo Attribute y opción Add Attribute que provee la propia instancia, pero el atributo me viene con sus propiedades todas en blanco y debemos escribir el name, el description y otros valores por defecto. Esto sin perjuicio de que cualquier nodo que hayamos borrado por error, siempre es recuperable haciendo botón derecho sobre el nodo de nivel superior y seleccionando “Add default <node>” que reconstruye el borrado con sus propiedades por defecto (no lo que hayamos modificado que eso sí, se pierde, a menos que usemos la opción UnDo que tenemos en el menú superior). Modes V1 01:29:30 El nodo Modes básicamente lo que establece son los modos de interacción por defecto, son determinadas acciones que vienen preprogramadas por la instancia y sólo debemos decidir si van o no van: Página 38 de 50 en la sección “Modes” de la columna derecha de Propiedades. Este nodo está orientado principalmente a los modos de la transacción: Insert, Update y Delete que son los tres modos que por defecto están habilitados (por “defecto” vienen en “True”). No así las otras acciones que hay, como el Dispaly (por “defecto” viene en “False”, porque el “General” del View de hecho brinda la misma funcionalidad), el Export a Excel que ya estaba presente en el WorkWith original y lo que hace es volcar a Excel los datos de todas las páginas de la Grilla (por “defecto” viene en “False”, pero si es requerido se puede pasar aquí expresamente a “True”) y el Chart que permite graficar el contenido de la Grilla. En este último caso no alcanza con pasar de “default” a “True”, sino que hay que definir otras propiedades antes que ese Chart funcione bien. Esas propiedades están en la sección “Graph” (arriba de “Modes”): 1. Cuál de los campos de la Grilla representa la entrada del Label a la gráfica. 2. Cuál de los campos de la Grilla representa los valores a graficar del Lebel. Este campo debe ser numérico para que funcione la gráfica. 3. Qué tipo de grafica se desea (de barras, de torta, de línea) Esta funcionalidad se encuentra disponible para el modelador Java y todavía no está disponible para el modelador Punto Net. Para el modelador Java se hizo además no dependiendo de GXChart (para el proyecto que estábamos trabajando era requerimiento obligatorio que fuera todo en ambiente Linux y no había acceso a Internet). No sería difícil implementar esta funcionalidad para Punto Net usando GXChart local o usando el servicio externo de Internet. Seguramente lo vamos a hacer cuando algún cliente lo requiera, porque ésta es la única funcionalidad de las PXTools que por ahora está resuelta sólo para la plataforma Java. Chart Width Chart Height y Chart Top lo agregamos recientemente: Página 39 de 50 porque cuando son muchos los datos de la Grilla, las medidas por defecto de la gráfica (500 por 400 pixeles) son insuficientes y no se quería cambiar este tamaño por defecto por una consulta especial. En ésta, casi toda la ventana quedaba ocupada por la muestra de los Labels y no se veía la gráfica en sí, de modo que fue necesario poder establecer un ancho y un alto para esta instancia particular. En la sección “Contitions”, arriba, en la columna derecha de Propiedades se establece, para cada una de las acciones del “Mode” que aceptan ser condicionadas, bajo qué condición queremos que se vean. Orders V1 01:36:58 El nodo Orders puede determinar más de un orden para el mismo WorkWith (botón derecho del mouse sobre el nodo Orders y Add Order) y cada orden puede tener múltiples atributos (botón derecho sobre el nodo Order y Add Attribute): Esto así declarado va a hacer aparecer el la sección de filtros de la pantalla (arriba de la Grilla) una opción para determinar el orden. Esto es así porque en la 9.0 todavía no tenemos la posibilidad de ordenar los registros de la Grilla directamente desde los títulos de cada columna (en la Rocha sí, esto está así implementado). De todos modos este nodo Order presta una funcionalidad adicional que es la de poder ordenar, no por una columna, sino por más de un atributo de la Grilla en orden preferencial. Página 40 de 50 El que vimos es el comportamiento por defecto, cada Order tiene un Caption (Nombre de Facultación, etc.) y lo que se muestra en la combo de selección de orden son estos Captions. A esto, en las PXTools le agregamos la posibilidad de definir una Condition (arriba, en la barra de Propiedades) para poder establecer dinámicamente un orden en función de ciertos datos que estamos mostrando o que estamos filtrando. Esto significa que si agregamos Conditions no tiene por qué aparecer la combo, salvo que tengamos más de un Order en que la condición da “True”. Entonces, para que aparezca la combo, es necesario que exista más de un Order cuya Condition de “True” al ser evaluada. Por ejemplo: En esta pantalla, si ingresamos el valor 100 en el campo de filtro Nro: seleccionado en la figura (Condition por Not Null), la grilla está ordenada por la columna “Comprob.” (decreciente). Si no ingresamos ningún valor en este campo (Condition por Null): la grilla viene ordenada por la columna Fecha (decreciente). Filter V1 01:41:34 Cuando las pantallas requieren Filtros, éstos se conceptúan en dos secciones, tal como ocurre con el WorkWith original: • La correspondiente al nodo Attributes, donde se declaran los campos que van a ser filtros Página 41 de 50 • que, como acabamos de ver, es lo que se muestra en la sección superior de la grilla. La correspondiente al nodo Conditions, donde se declaran las condiciones que deben cumplir los registros de la propia grilla y que por lo general van directamente a las Conditions del Web Panel generado, porque por ahora los éstos soportan una sola grilla. Cuando hacemos un Select Attribute (botón derecho del mouse sobre el nodo Attributes y elegimos uno, por ejemplo: CliObs, en la ventana pop up de selección del atributo) el sistema nos pregunta en una nueva pop up: “Add corresponding filter conditions?”. Se trata de una ayuda al programador para que, al agregar un atributo, el sistema agregue automáticamente la condición más cercana a ese atributo con un valor tentativo. En este caso, al haberle dicho que sí, me agregó el CliObs like &CliObs when not &CliObs.Empty() (como puede verse en la figura siguiente). El “when” es una funcionalidad que creo que es de la 9.0 y lo que está determinando es que se active este filtro (CliObs like &CliObs) para los registros de la grilla, cuando suceda determinada situación: (not &CliObs.Empty()). Página 42 de 50 Después que el sistema hizo esta correlación entre el atributo CliObs y esta Condition podemos abrir la propiedad “Value” y cambiarla a gusto del consumidor. Se trata simplemente de ayudar al programador a instanciar una condición precargando un valor, pero después podemos cambiarlo según los requerimientos reales de la aplicación. Vamos a ver ahora como podemos representar en forma horizontal un conjunto de campos de filtro, como vimos en la figura 11:40:44. Esto vale también para cualquier otra sección donde debamos colocar datos en pantalla y podamos acceder a esta nueva entidad que nosotros llamamos “Category”. En este caso, botón derecho del mouse sobre el nodo Attributes y seleccionamos “Add filter Category”. Luego para meter el atributo CliObs dentro de este nuevo Category, primero lo cortamos (botón derecho sobre el atributo y “Cut”) y después lo pegamos (botón derecho sobre el Category y “Paste”): El Category cumple dos objetivos: Página 43 de 50 • Categorizar (agrupar) un conjunto de atributos y/o variables, eventualmente bajo un mismo título (Description del Category). Esto en Win se resolvía poniéndolos dentro de un rectángulo, por ejemplo. • Organizar horizontalmente todos los atributos y/o variables que contenga como elementos subordinados. Pasa también en el Form de tipo tabular de la Transacción, en los Filtros, o en el Tab General del View que estos elementos se ubican uno encima del otro mientras que a veces queremos representarlos horizontalmente y el Category cumple esa funcionalidad: Todos los elementos que estén debajo de un Category van a estar representados horizontalmente, cada uno a la derecha del anterior. Esto en principio, pues después vamos a ver que también tenemos recursos para atender su alineación vertical cuando hay más de un Category. Si agregamos otro Category en la sección de Filtros (botón derecho sobre Attributes y Add Category), minimizando todos los nodos debajo del de Attributes vemos la cantidad de filas reales que va a tener la sección: en este caso tres: La del atributo CliNomFac, la del Category CliObs y la del nuevo Category que acabamos de crear. Si no le ponemos “Description” al Category en la barra de Propiedades, éste no cumple la función de titular (poner un Título) sino de representar horizontalmente. No va a ocupar un espacio en la pantalla la ausencia de este Título. En el caso de la figura 11:40:44, los Filtros se resolvieron mediante un Category con “Situar en:” como Description (que sería el Título) y después Página 44 de 50 todas las variables (Fecha, Tipo, Nro, etc.) se declararon dentro de ese mismo Category y se representaron todas horizontalmente. Parameters V1 01:48:55 El nodo Selection no tiene precargados por defecto todos los nodos subordinados. Vamos a ver que tenemos bastantes nodos adicionales que podemos agregar (botón derecho sobre el nodo Selection y Add…): aquí vemos todos los que pueden estar en el juego dentro del Selection. Vemos que se pueden declarar Parameters dentro del WorkWith. Si estamos trabajando con el WorkWith principal, por lo general no va a tener parámetros. Pero si estamos trabajando con unos WorkWith internos, que se relacionan unos con otros, puedo necesitar tener que declarar parámetros. En este último caso, es simplemente hacer botón derecho sobre el nodo Parameters y Add parameter: y declarar en la barra de Propiedades, el Name del parámetro (vamos a ver en cada caso cuando aplican las propiedades NullValue e Instanced). Si asumimos que la Transacción de Clientes tenía al País de Residencia para poder ver los Clientes de un país, podríamos poner PaiCod como atributo y ya automáticamente, al definir un valor para este atributo, me va a filtrar por ese valor. Podría tratarse de una variable del tipo &PaiCod en cambio y en ese caso tendríamos que declarar una nueva Condition dentro del nodo Conditions Página 45 de 50 del nodo Filter, que sea PaiCod = &PaiCod. Si declaro el Name del Parameter como variable tendría que definir explícitamente la condición para que realice el filtro, si lo declaro como atributo, no. Actions V1 01:55:50 Entrando ahora en el nodo Actions, vamos a agregar una Acción (botón derecho sobre Actions y Add action). Al seleccionar el nuevo nodo Action, la barra de Propiedades muestra las siguientes opciones: Se pueden catalogar las Acciones según dos criterios: • Por un lado tenemos la propiedad Control Type donde se declara si el control de la acción es de tipo Imagen o de tipo Texto Página 46 de 50 • Si es de tipo imagen va a ser un ícono prediseñado y si es de tipo Texto va a ser un botón con el texto encima. Por otro lado tenemos la propiedad InGrid, que puede estar en “True” o “False”. Por ahora no tenemos implementada la funcionalidad del selector de líneas de la Grilla (que nos permitiría poner todas las acciones fuera de la misma gracias a una nueva funcionalidad de la 9.0), por lo tanto, aquellas acciones que aplican sobre un registro de la Grilla deben ser declaradas como InGrid: True y van a ser colocadas en columnas que se agregan a la Grilla. Se trata de acciones que van a tomar parámetros que son datos del registro. En cambio, si la acción no depende de los datos de ningún registro de la Grilla, se declara InGrid: False y los íconos o los botones van a ubicarse fuera de la Grilla. Todas estas propiedades pueden combinarse. En particular si la acción es InGrid y el Control Type es Image, cada imagen va a ocupar una columna de la Grilla y si el Control Type es Text, hicimos un cambio respecto a WorkWith original. En lugar de agregar una columna para cada acción de texto, concentramos todas ellas en una sola columna mediante una Combo Box en cada registro (de modo de no ensanchar innecesariamente la Grilla con una cantidad de columnas que terminan no dejando ver las columnas significativas). Ambos comportamientos pueden apreciarse en la siguiente pantalla: Página 47 de 50 donde en las primeras cuatro columnas se ubican otras tantas acciones InGrid de tipo Imagen y en la quinta otras tres acciones de tipo Texto. Variables V1 01:59:28 El nodo Variables nos brinda la posibilidad de definir variables explícitas en el WorkWith, variables que se cargan en el Evento Load del nodo Selection y que nos permiten incluso amar una Grilla en la que todos sus elementos sean variables (sin Tabla Base). En este caso debemos hacer el Event Load “a mano” (hacer el For Each y poner el comando Load). Para esto debemos usar la propiedad Load Code que representa el Event Load del Web Panel y cuando lo seleccionamos se nos abre una ventana pop up: para que podamos ingresar el código con el que vamos a resolver la carga de las variables con las que se va a armar la Grilla. Este editor es bastante malo, pero habitualmente en procesos de migración, lo que tenemos que hacer es copiar y pegar el Event Load del Work Panel que estamos migrando. Esto así se ve muy sencillo pero por adentro, el generador debe incorporar el código requerido para soportar todo el tema del paginado. Página 48 de 50 Quiero decir que todas las tuplas que se cargan con este Load, se deben ir parseando para después poder mostrarse con las mismas funcionalidades de paginado de Grilla que vimos cuando existe Tabla Base. Por otra parte, en este Event Load puedo estar definiendo además variables auxiliares, u otras variables para que almacenen valores intermedios que necesitemos conservar y todas estas variables, al no estar declaradas, van a provocar los típicos “warnings” de GeneXus. Entonces, para poder declarar todas estas variables es que está el nodo Variables, donde (botón derecho sobre Variables y Add variable): podemos definir en forma explícita cada una de las variables que vamos a usar. Fixed Data • • V1 02:02:12 El Fixed Data se compone de dos elementos: El Bottom Fixed Data que es una información que queremos mostrar después de la Grilla: El Top Fixed Data que es una información que queremos mostrar antes de la Grilla. Página 49 de 50 Entonces, el Fixed Data cumple esa funcionalidad: Mostrar variables que queremos ubicar antes o después de la Grilla. Caso típico: Saldo Inicial, Movimientos (en la Grilla), Saldo Final. Una vez que agregamos el Top Fixed Data (botón desecho sobre Fixed Data y Add top Fixed Data) aparece el nodo Attributes y podemos diseñar su contenido (botón derecho sobre Attributes y Add …) agregando los nodos que correspondan: Category, Attribute, Variable, etc. Por lo general son variables las que se definen. Después podemos agregar el Bottom Fixed Data y aparece debajo otro nodo Attributes con las mismas funcionalidades que el anterior. Son dos Forms tabulares, por lo que, si quisiéramos mostrar datos horizontales, aplica lo del Category. Antes de que me lo pregunten les diré que por el momento no es posible, en caso de que haya varios totales de columnas de la Grilla, ubicarlos justo debajo de esas columnas, entre otras razones porque si los contenidos de la Grilla son muy extendidos, la misma genera un scroll horizontal. Y aunque no se genere el scroll es imposible saber la ubicación exacta de una columna porque depende de los contenidos particulares de las columnas anteriores. El único modo sería ver si a nivel de HTML es posible meter esos totales dentro de la propia Grilla, pero por ahora no se puede ni arriba ni abajo, alinear estos valores con las columnas de la misma. Página 50 de 50