Etiqueta

12 de agosto de 2015

Objetos externos (External objects)

Los objetos externos pueden ser manejados mediante la creación de un tipo especial de componente referenciado como “no visual”. Todos ellos se encuentran ubicados dentro de la carpeta Xcomp que (a su vez) podemos encontrar dentro del directorio raíz de instalación de Omnis Studio. Pero no todos los Xcomp pueden ser utilizados de éste modo. De hecho, la mayoría de los Xcomp sólo contienen objetos “visuales”, los cuales podemos colocar en ventanas, formularios e informes, pero, incluso algunos de éstos también contienen algún componente “no visual” que podemos utilizar como clase base, en la construcción de la variable objeto (variable de tipo “”Object”) o bien como superclase de una clase de tipo objeto (clase de tipo “Object”).

Existen relativamente pocos de estos Xcomps especiales. Una manera de descubrirlos es navegar a través de la lista de componentes externos disponibles, mediante abrir el enlace correspondiente desde el Explorador de Omnis Studio. Tal y como se muestra el siguiente imagen:



Explorando los componentes externos


Cómo podrá comprobar existe un gran número de componentes externos. Pero sólo el hecho de su aparición, no significa que esté siendo usado por Omnis Studio, ya que primero deberán ser cargados en memoria. La forma más sencilla de hacerlo es mediante indicar su estado de precarga, tal como se puede observar a continuación:



En éste artículo nos centraremos en los componentes recogidos bajo el grupo “External Components”. Si lo ampliamos podremos ver algo similar a los siguiente:



Podríamos mantener componentes alojados en cualquier parte de nuestro sistema, pero lo mejor es agruparlos en la carpeta Xcomp.

Los componentes actualmente cargados se muestran en la lista con un punto verde y los que no, con un punto rojo. Podemos configurar cualquiera de ellos para que sea cargado al iniciarse Omnis o bien al abrirse la librería en uso, mediante hacer clic en el botón de la opción correspondiente. Tenga en cuenta que el color del punto no cambiará inmediatamente, ya que los cambios no se verán reflejados hasta la próxima vez que abramos ésta ventana de configuración. Pero si podremos hacer uso de los cambios introducidos sin necesidad de reiniciar Omnis Studio, no cerrar y volver a abrir nuestra librería.

Los elementos se muestran bajo la denominación “libraries”, y es una denominación apropiada, pues a medida que vamos recorriendo los diferentes elementos de la lista, enseguida nos damos cuenta de que muchos de ellos contienen a su vez varios componentes. Mostrados a la derecha, podemos ver los nombres de dichos componentes, junto con iconos representativos del tipo al que pertenecen. Éstos pueden ser: Ventana, Informe y Objeto. Los componentes “Remote Form”” están localizados en la lista bajo un grupo diferente denominado “Form External Components”, pero en este artículo, deseamos centrarnos en el uso de los componentes de tipo Objeto (Object), son los mostrados mediante un icono en forma de caja y con un enchufe saliendo de ella.




En el dibujo anterior, podemos ver los controles que integran el componente “Graph2”. Observe la existencia de tres controles, uno de tipo ventana, otro de tipo informe y otro de tipo objeto.

Una vez que el componente externo ha sido cargado por Omnis, podrá ser usado con diversos fines dentro de nuestra librería. Un modo de hacerlo, es mediante localizar cualquier componente con interfaz gráfica de usuario, desde el “Component Store” y arrastrarlo sobre la posición que deseemos durante el diseño de una clase apropiada para su uso. Pero cuando se trata de componentes de tipo objeto “no visuales” su modo de uso es diferente.

 

Uso de un objeto externo (External Object)


Existen dos formas básicas de uso. 1) Seleccionar el componente de tipo objeto, como subtipo en una variable de tipo objeto o especificarlo más adelante mediante el método “$new()”. 2) Disponer el componente de tipo objeto, bajo el atributo superclase (superclass) en una “Object Class”. Pueden existir diferentes razones por las que preferir una u otra técnica.

Por el momento, vamos a utilizar la segunda técnica, ya que nos da la oportunidad de explorar fácilmente las propiedades y métodos del objeto. De modo que vamos a crear una nueva “Object Class” con el nombre “timerObject”, después y mediante el “Property Manager”, vamos a asignarle el xcomp “Timer” como superclase de nuestra recién creada “Object Class”. Tras hacer clic sobre el valor para ésta propiedad, aparecerá el diálogo que nos permite realizar su elección de entre la lista de componentes. Observe que sólo se muestran los xcomps de tipo objeto:




Ahora podemos abrir la clase “timerObject” y ver su contenido. Observe que la “Object Class” ha heredado los métodos y propiedades del componente externo. Tras abrir la clase, podemos visualizar dichos métodos en el editor:



Los elementos heredados aparecen (por defecto) en azul. (ver $root.$prefs): 



La “Inheritance”  (herencia) es una característica de la programación orientación a objetos soportada por Omnis Studio. Cada vez que se cree una instancia de nuestro objeto, recibirá los métodos y propiedades de la superclase.

Puede darse el caso de que queramos sustituir un método heredado, por otro nuestro, pero manteniendo su actual nombre, con el único fin de sustituir su código o acción por defecto. Puede que incluso tangamos imperiosas razones para hacerlo así en éste caso, ya que el método denominado “$timer” es el método invocado cuando el cronómetro (en su cuenta atrás) llega a cero. Tras su herencia, está vacío, por lo que debemos hacer un “overriding”, a fin de anular su acción por defecto. A continuación mostramos como hacerlo:




En éste caso el método se hereda vacío, pero también puede suceder que deseemos reemplazar un método que realmente hace algo. Por ejemplo, tal vez necesitemos añadir un par de pasos adicionales al método “$resettimer” a fin de reiniciar otras variables. Tenga en cuenta que aunque hayamos anulado y sustituido el método por el nuestro propio, podemos seguir invocándolo para su ejecución desde cualquier punto del método mediante el comando “Do inherited”, tal y como mostramos a continuación:



El editor de métodos nos permite ver los nombres de los métodos heredados, pero el “Interface Manager” nos permite ver un poco más. Accedemos a la “Interface Manager” desde el menú “View” del editor de métodos. En la siguiente imagen, puede observar como es posible ver los métodos y las propiedades, así como información adicional de ayuda:



Desde aquí, podemos examinar los parámetros disponibles para el método seleccionado y leer su descripción. En el caso de métodos no heredados o anulados, podemos optar por incluir nuestras propias descripciones. La pestaña de propiedades nos permite leer la descripción de la propiedad seleccionada. A continuación veremos un segundo modo de hacer uso de un objeto externo.

Consiste en simplemente heredar (inherit) la funcionalidad del Xcomp directamente sobre una variable de tipo objeto. La forma más sencilla de hacerlo es mediante indicar la xcomp a utilizar, reflejándola como subtipo de la variable de objeto, desde el panel de definición de variables.




Una variable “Object” definida de esta forma, hereda todos los métodos y propiedades que vimos anteriormente para la “Object Class”.

Si deseamos examinar sus métodos y propiedades con mayor detalle, puede optar por abrir el “Interface Manager” desde el menú contextual de la propia variable:




Si lo preferimos, podemos hacer uso del método “$new()” para crear una instancia de la variable objeto, indicando al mismo tiempo el xcomp a utilizar. Dado que la mayoría de éstos xcomps no contienen un método “$construct”, no hay mucha razón para hacerlo, pero ciertamente está permitido. El modo sería la siguiente:


Tenga en cuenta que debemos indicar el nombre de la librería de componentes, seguido de “$objects”, con el fin de poder localizar el nombre del elemento de entre los tres, que la componen.

Por último, indicar también que podríamos hacer uso de una variable de tipo “Object reference” en lugar de una variable “Object”. Recuerde que esta variable (o puntero) deben ser usadas mediante  el método “$newref()” en lugar de “$new()”, tal y como mostramos a continuación:


La única desventaja de esto, es que no se nos permite utilizar el “Interface Manager” para ver los métodos y propiedades del objeto mientras trabajamos.

Gracias por su atención.

5 de agosto de 2015

Gestión de sub-formularios dentro de un mismo panel o “Paged Pane”.

En éste artículo queremos destacar una, de las muchas cosas que nos ha traído la versión 6 de Omnis, se trata de la posibilidad de gestionar un grupo de subformularios dentro de un mismo contenedor, creando un efecto de paneles plegables al estilo de lo que sucede con el menú de un “Paged Pane”. Los diferentes subformularios quedan dispuestos verticalmente pudiendo ser expandidos o contraídos, haciendo clic/tocando sobre su barra de título o bien sobre el icono dispuesto al efecto


Configuración de los paneles


Para crear el grupo de paneles tendremos que hacer uso del método “clientcommand”  denominado “subformset_add”, junto con algunos nuevos parámetros, cuyas constantes podremos encontrar bajo el grupo ”Subform sets” y con el epígrafe “kSFSflag...”. El comando “subformset_add” creará el conjunto de subformularios dentro de la instancia “remote form” actual, tal y como si se tratase de un “Paged Pane”.

Do $cinst.$clientcommand("subformset_add",row-variable)

La variable de tipo “row” es definida como: row(grupo,padre,flags,orden,lista). A continuación describimos las principales banderas o “flags” que pueden ser usadas con el comando “subformset_add”.

kSFSflagOpenMin

Éste “flag” o bandera causa que el grupo de paneles se abra en estado minimizado. Normalmente, todos los subformularios se abren en estado de no-minimizado, de modo que deberemos hacer uso de ésta bandera para evitar su comportamiento predeterminado.

kSFSflagMinAsTitle

Cuando se minimiza un panel (subformulario) del grupo, se mostrará sólo la barra de título. Esta bandera anula su comportamiento predeterminado y que es ocultar completamente (cerrar) el subformulario. Para añadir el botón de minimizar a cada subformulario, deberá usarse la bandera “kSFSflagMinButton”, lo cual permite al usuario expandir o contraer el panel mediante su pulsación y no sólo mediante hacer clic en su título.

kSFSflagAutoLayout

Dispone automáticamente los paneles (subformularios del grupo) verticalmente dentro de su matriz, ignorando su posiciones originales “left” y “top”. Se activa la bandera  “kSFSflagMinAsTitle” y se desactivan “kSFSflagResize” y “kSFSflagMaxButton”. Si además activamos “kSFSflagAutoLayout”, el usuario podrá arrastrar y soltar la barra de título de los diferentes paneles del grupo, para reordenarlos, colocándolos en el orden que prefiera.

kSFSflagParentWidth

Sólo es aplicable si antes se ha activado “kSFSflagAutoLayout”. Su posición original “width” (ancho) será ignorada, tomándose en su lugar el ancho del subformulario “padre” para todo el grupo. También fija el “edgefloat” de cada subformulario a “kEFright”. De modo que, el uso de “kSFSflagParentWidth” nos permite, la creación de un “Paged Pane” compuesto a modo de varios paneles creados a partir de un grupo de subformularios, que se redimensionan o ajustan automáticamente dentro del panel que los contiene.

kSFSflagSingleOpen

Sólo es aplicable si antes se ha activado “kSFSflagAutoLayout” y “kSFSflagMinButton”. Permite asegura que al menos una ventana o panel esté siempre abierto.

 

Un ejemplo vale más que mil palabras


La imagen que mostramos al inicio de éste artículo, muestra un conjunto de paneles o grupo de subformularios contenidos en un “Paged Pane”, con las opciones “Auto Layout” y “Parent Width” activadas.

El método que mostramos a continuación, construye el grupo de subformularios asignándolo a un “Paged Pane” colcado a su vez dentro de un “remote form”. En el ejemplo, el subformulario tan solo contiene un campo de edición, con un pequeño texto ("This is panel #"). La lista o grupo de subformularios es construida incluyendo dicho texto, además del color de fondo, todo dentro de la variable “row” indicada para en el método “clientcommand” y su opción “subformset_add”.

; defina las variables para “lFormList”, “lSetRow” y para todas sus columnas
; construya el grupo de subformularios sobre “lFormList”
Do lFormList.$define(lFormID,lClassName,lFormParams,lFormTitle,lFormLeft,lFormTop,lFormWidth,lFormHeight)
Do lFormList.$add(1,'jsSubformSetPanelsSubForm',con(1,chr(44),rgb(221,221,255),chr(44),chr(34),"This is panel 1",chr(34)),'Panel 1',,,,160)
Do lFormList.$add(2,'jsSubformSetPanelsSubForm',con(2,chr(44),rgb(204,204,255),chr(44),chr(34),"This is panel 2",chr(34)),'Panel 2',,,,160)
Do lFormList.$add(3,'jsSubformSetPanelsSubForm',con(3,chr(44),rgb(187,187,255),chr(44),chr(34),"This is panel 3",chr(34)),'Panel 3',,,,160)
Do lFormList.$add(4,'jsSubformSetPanelsSubForm',con(4,chr(44),rgb(170,170,255),chr(44),chr(34),"This is panel 4",chr(34)),'Panel 4',,,,160)
; defina la variable “row” para el comando “subformset_add” como “lSetRow”
Do lSetRow.$define(lSetName,lParent,lFlags,lOrderVar,lFormList)
Do lSetRow.$assigncols("SubformPanelsSet",'PagedPane:1',kSFSflagSingleOpen+kSFSflagMinButton+kSFSflagAutoLayout+kSFSflagParentWidth,'iOpenForms',lFormList)
Do $cinst.$clientcommand("subformset_add",lSetRow)

En este caso las banderas “kSFSflagSingleOpen”, “kSFSflagMinButton”, “kSFSflagAutoLayout” y “kSFSflagParentWidth” son sumadas para dotar al grupo en construcción de todas las propiedades simultáneamente.

29 de julio de 2015

Controlando la entrada de datos en formularios (Form Errors)

Ahora es posible mostrar etiquetas de error, que guíen al usuario durante la introducción de valores en los campos de un formulario web, podremos hacer que (dichas etiquetas) se muestren a la derecha o debajo de los campos de entrada de un "remote form". Esta nueva característica hará más fácil a los usuarios rellenar formularios en la web y en nuestras aplicaciones móviles, de éste modo podremos realizar una validación dinámica e interactiva del formulario. Los errores aparecen en el formulario como etiquetas de texto "text field", y situados bajo un control o a su derecha, por lo que será necesario diseñar los "remote form" de modo que dejen el espacio necesario para que sea posible mostrar el texto de error. El estilo del texto, puede indicarse mediante HTML o CSS.


Descripción y uso de sus propiedades


$errortext


Todos los controles "jsClient" soportan la propiedad "$errortext", ésta propiedad es la que deberá contener el texto a mostrar cuando se produzca un error sobre el campo o control en uso. Inicialmente no contendrá valor alguno.

$errortextpos

La propiedad "$errortextpos" permite especificar la posición del texto de error. Sus posibles valores son:
  • kJSErrorTextPosUnder (El texto de error será mostrado bajo el control. Es también, su valor predeterminado.)
  • kJSErrorTextPosRight (El texto de error será mostrado a la derecha del control.)

Tenga en cuenta que Omnis deberá guardar valores para cada "$errortextpos", según los diferentes y posibles tamaños de pantalla. Durante el diseño del formulario, deberá mantener pulsada la tecla "control", para asignar un valor diferente según los tamaños de pantalla a soportar.

$errorline

La propiedad "$errorline" sólo puede ser usada en modo "tiempo de ejecución" o "runtime" y permite la asignación de "$errortext" a un objeto localizado dentro de una fila en un control "Complex Grid". Contendrá el número de la fila sobre la que aplicar el texto.

 

Eliminación de los textos mostrados


Un nuevo comando de tipo "client command", denominado "clearerrors" nos permite eliminar todos los mensajes de error mostrados sobre un formulario.

Do $cinst.$clientcommand(“clearerrors")


Ésta acción es equivalente a la asignación de un "$errortext" vacío para todos los controles del formulario con texto de error asignado.

 

Modificación del estilo del texto


A continuación indicamos las clases CSS que controlan la apariencia y bordes del texto. Podrá encontrarlos sobre el fichero "omnis.css".
  • div.om-error-text (Clase con lo estilos aplicables el texto de error.)
  • div.om-error-border (Configura los márgenes del "div" con el texto de error.)