Etiqueta

Mostrando entradas con la etiqueta #AULAOMNIS. Mostrar todas las entradas
Mostrando entradas con la etiqueta #AULAOMNIS. Mostrar todas las entradas

4 de marzo de 2019

Uso de iconos en Omnis Studio (Parte 2 de 2)

Importante indicar en primer lugar, que los procedimientos que permite guardar iconos en #ICONS o en archivos (como “Omnispic”) asignándoles un ID ($iconid), por compatibilidad hacia atrás, continúan funcionando, pero ahora sólo resultarán útiles con iconos en 16x16 pixeles. Debemos tener en cuenta, que si nuestras aplicaciones son ejecutadas en una pantalla HD y nuestras librerías aún usan éste tipo de iconos, Omnis intentará localizar un ícono correspondiente en 32x32, de no existir se usará la imagen 16x16 pero su apariencia visual resultará muy pobre. Para conseguir que sus antiguos iconos 16x16 se vean bien en alta definición, deberá crear una nueva versión de cada imagen a 32x32 píxeles e importar cada una de ellas al archivo de datos o #ICONS, bajo la sección 32x32 que encontrará en la misma página de iconos, usando los mismos identificadores o ID, que los usados con la versión 16x16.


Si ha estado ya utilizando iconos en 32x32 o 48x48 píxeles en sus librerías y lo que quiere es que se vean correctamente en pantallas HD, deberá adaptar sus actuales librerías para su uso con el nuevo “Iconsets Studio”, lo cual implica disponer de archivos de imagen separados y ubicados en carpetas, las cuales permiten la inclusión de imágenes para iconos de hasta 96x96 píxeles (es decir, 2 veces el tamaño del icono más grande el de 48x48. Los “iconsets” son compatibles tanto con las clases “remote-form”, como con las habituales clases “window”, pero no podrán usarse con los antiguos plug-in ”’Web Client”, e 'iOS Client’.

Denominación de archivos imagen


Cada archivo de imagen dentro de un conjunto de iconos, deberá seguir la siguiente convención: 

texto_id_tamañoyestado_resolución.png

  • "texto" Es el nombre de la imagen. Aparecerá en el cuadro de diálogo del selector de iconos, mientras asigna el “$iconid” de un objeto.
  • "id" es el ID (valor entero positivo) utilizado como ID del icono. Deberá estar en el rango de 1 a 10.000.000 
  • "tamaño" es el tamaño expresado en píxel CSS de la imagen independiente de su resolución, lo que significa que éste valor no cambiará, para con todas sus diferentes resoluciones. Su valor debe ser expresado en la forma “x”, los valores 16x16, 32x32 y 48x48 deberán existir siempre, ya que corresponden a los tamaños estándar admitidos por Omnis.
  • "resolución" es el factor que identifica su densidad de píxeles, la cual deberá expresarse del modo siguiente:  
    • "_ 2x" para dispositivos HD o pantalla Retina.
    • "_15x" para ciertos dispositivos, como por ejemplo teléfonos con una densidad de píxeles de 1.5x. no será necesario especificar valor alguno para dispositivos con una resolución estándar, o equivalente a _1x

Los archivos (o nombres de carpetas) que no cumplan con las convenciones especificadas serán ignorados.

Ejemplos válidos de nombres de archivo son: 

pencil_1657_16x16.png 
Icono con "estado" normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución estándar
pencil_1657_16x16_2x.png 
Icono con "estado" normal, de tamaño 16x16, con ID 1657, para dispositivos con resolución HD
check_1658_32x32c_2x.png 
Icono con estado “c”, de tamaño 32x32, con ID 1658, para dispositivos con resolución HD (ver más abajo lo que significa su "estado"

Se deberá tener en cuenta que los nombres de los archivos de imagen no distinguen entre mayúsculas y minúsculas y deben ser únicos para con todas la plataformas y sistema de archivos (los nombres repetidos serán ignorados).

Iconos para casillas de verificación


Como caso especial, es posible implementar iconos que permiten diferentes estados, tales como casillas de verificación y botones-radio.

  • "estado" es el estado en que se encuentra el icono (“marcado”, “resaltado” o “normal”) y puede ser uno de los siguientes: (dejarlo en blanco indica su estado “normal”).
    • “c” corresponde a la situación de “marcado” del icono
    • “h” corresponde a la situación de “resaltado” del icono
    • “x” corresponde a la situación de “marcado” y “resaltado” del icono
Si no está seguro de que iconos necesitará crear y cual será su denominación, puede optar por examinar los contenidos en la carpeta “iconsets/studioide”, aquí podrá encontrar archivos de imágenes de diferentes tamaños, tal y como son requeridos para su uso con Omnis Studio. Pero tenga en cuenta que no puede usar los iconos de esta carpeta, sin adquirir antes la licencia adecuada. Use un esquema de nombres similar a éste para con sus propias creaciones.

Imágenes escaladas


No es estrictamente necesario crear una imagen del icono para cada una de las posibles resoluciones, aunque sería recomendable hacerlo si se desea obtener una mejor apariencia. No obstante Omnis puede hacer uso de la imagen que mas se acerque a la resolución deseada, escalando la misma, en éstos casos es mejor forzar a que sea el propio Omnis quien efectúese el escalado en lugar de hacerlo nosotros mismos. En estos casos, lo mejor será proporcionar a Omnis la imagen con la mayor resolución posible, para dejar que Omnis reduzca las imágenes de resolución más baja, pero tenga en cuenta que el escalado puede producir resultados no esperados.

Cuando se produce una conexión (aplicaciones Web), el cliente envía su resolución al servidor de aplicaciones Omnis. Lo cual permite a Omnis hacer uso  del ícono apropiado.

Preguntas frecuentes


¿Cómo hacer uso de Imágenes con tamaños “no estándar”?

Naturalmente podemos disponer de imágenes de tamaño diferente al estándar (16x16, 32x32, 48x48) siempre y cuando incluyamos en su nombre de archivo las especificaciones de tamaño. Por ejemplo, podemos crear una imagen de 100x200 píxeles, nombrándola como "midibujo_1688_100x200.png", su versión en alta resolución (a 200x400 píxeles), tendría como nombre ”midibujo_1688_ 100x200_2x.png”, (esto sería equivalente a una “Icon Page” de Omnis )

¿Cómo agregar “Iconsets” al servidor de aplicaciones web?

Cuando se trate de una aplicación que queremos hacer disponible en la Web, necesitaremos copiar todos los “inconsets”utilizados en nuestros formularios desde el directorio “/iconsets” en de nuestra versión “developer” a la carpeta “/icons” situada al mismo nivel que nuestros archivos “.htm” de nuestra aplicación, es decir, en el lugar donde estén ubicados nuestros ficheros “.htm” en el servidor web: cada “iconsets” deberá aparecer como una sub-carpeta de la carpeta “/icons” y deberá contener todos los archivos PNG que precise nuestra aplicación.

¿Cómo configuro mi librería para el uso de “inconsets”?

Las librerías poseen una preferencia denominada “$iconset” ($libs.LIBRERIA.$Prefs) y es aquí donde deberá figurar el nombre del “iconset” que usaremos con nuestra librería, de éste modo Omnis sabrá dónde buscar los identificadores de nuestros iconos. En cada ocasión que trabajemos con esta librería, Omnis buscará los iconos dentro del “iconset” especificado para ella, antes de hacerlo en el resto de posible ubicaciones.

¿Cómo gestiona Omnis los posibles errores al asignar un ID?

Cualquier error causado al configurar el ID de un icono para los objetos, será enviado a un archivo de errores denominado “iconsetlog.txt” ubicado en la carpeta “html”.

¿Puedo hacer uso de imágenes mediante la indicación de una URL?

Al asignar el “$iconid” para un objeto bajo “jsClient”, podemos optar por indicar una URL. Si el valor asignado consiste en una cadena de caracteres que contiene al menos un carácter ”/“, Omnis lo tratará como una URL generada por la función “iconurl”, esto significa que podremos referenciar archivos de iconos alternativos, según las diferentes resoluciones de pantalla de los clientes, Omnis elegirá el icono correcto. En caso de hacerse la asignación mediante programación y siempre que el valor asignado no sea un ID de icono (un entero o un entero + una constante de tamaño), Omnis entenderá que se trata de una URL generada por la función “iconurl” eligiéndose el correspondiente a la resolución del cliente. Las URL’s que necesite podrán ser generadas mediante el uso de la función “iconurl()” en el método “$construct()” del “remote-form” y ser guardadas en una variable de tipo “list” en el ámbito de la instancia, con el fin de usarlas en el código que realice la asignación de imagen a los diferentes objetos.

¿Cómo gestionar dinámicamente la asignación de imágenes, para (por ejemplo) un componente “tree lists”?

Los “Tree control” de jsClient, han sido modificados, de modo que su columna “iconid” ahora es “iconurl”, y su propiedad “$iconurlprefix” ahora resulta redundante, aunque se sigue manteniendo por compatibilidad hacia atras. La columna “iconurl” deberá ser definida como de tipo carácter y rellenarse utilizando una función “iconurl(iconid)”, que devuelve una cadena URL con el nombre del archivo de imagen o bien una lista separada por punto y coma, con los nombres de los archivos en caso de iconos con varias resoluciones. Esto es lo que permite a Omnis elegir el icono correcto según la resolución de pantalla del cliente conectado.

28 de diciembre de 2018

Nueva herramienta de migración de Omnis DF1 a SQLite o PostgreSQL

Otra de las novedades que incluye Omnis Studio 10, supone una garantía de estabilidad y longevidad para nuestras aplicaciones, especialmente en lo que al uso de la base de datos nativa (los llamados df1) se refiere. La gran ventaja que supondrá el uso de ésta herramienta es, que tras su conversión a una base de datos SQLite o PostgreSQL, los antiguos comandos denominados "Omnis DML" permanecerán en la biblioteca convertida, pero, (y este es el importante detalle) se ejecutarán contra la base de datos seleccionada (SQLite o PostgreSQL), sin problemas y automáticamente, en lugar del antiguo fichero de datos Omnis. Por ejemplo, comandos como "Prepare for edit" o "Update files" se ejecutaran contra la nueva base de datos (SQLite o PostgreSQL). 



Sin duda ésta opción, es muy bien recibida por todos aquellos que hemos deseado por mucho tiempo, disponer de un almacenamiento de datos más robusto, proporcionándonos a la vez, una cómoda puerta de salida, en la migración de nuestras antiguas aplicaciones hacia el soporte de código SQL. Un mejorado "OmnisSQL DAM" será el encargado de producir el "milagro" de acceder a un fichero SQLite como si se tratase de un antiguo fichero .df1

Se han realizado pruebas con el nuevo "OmnisSQL DAM" contra archivos de datos SQLite y Omnis, tanto directamente como utilizando "Data Bridge". Las pruebas se han realizado insertando ~ 2.5MB y leyendo ~ 20MB de un archivo de datos. Los tiempos de finalización de la prueba se muestran en segundos.


27 de diciembre de 2018

Objetos "JavaScript Worker"

Omnis Studio 10, ahora tiene embebido (integrado) el "framework" "node.js", el cual incluye gran cantidad de módulos de código abierto desarrollados por terceros y que (por tanto) podremos usar libremente desde nuestro código Omnis. Un nuevo "Worker Object" denominado "JavaScript Worker Object" nos permitirá ejecutar métodos de "node.js", mediante simplemente invocarlo desde nuestro código Omnis, para posteriormente recibir los resultados en el método indicado como retorno del mismo. A modo de ejemplo, Omnis incluye la librería "xml2js" la cual permite convertir un XML a JSON.

Construcción de métodos JavaScript


Con éste fin Omnis dispone de un nuevo archivo JS, denominado "ow3javascript.js", el cual podremos localizar bajo el directorio "clientserver/server/remotedebug" y que es el punto de partida para todas las llamadas a los métodos de "node.js". Éstas llegaran desde Omnis como solicitudes HTTP y retornaran sus resultados también como contenido HTTP. Cada "Worker" ejecutará sus métodos secuencialmente.

Un nuevo directorio o carpeta denominada "node_modules", contendrá los módulos que serán requeridos desde el "ow3javascript.js". Es aquí, donde deberemos ubicar lo módulos "node.js" que deseemos utilizar, mediante el comando "npm -i" ejecutado desde ésta misma carpeta; éstos serán los módulos que ineraccionaran con nuestras aplicaciones Omnis.

Existen al menos dos archivos clave que siempre deberán estar ubicados y presentes en ésta carpeta:

  • omnis_calls.js - Módulo que encargado de devolver los resultados a Omnis.
  • omnis_modules.js - Módulo encargado de suministrar la lista de los que podrán ser invocados desde Omnis.

En ésta misma carpeta, podremos localizar dos módulos suministrados a modo de ejemplo denominados: "omnis_test.js" y "omnis_xml2js.js". Vistos desde Omnis sus nombres son "test" y "xml2js", a cada uno de ellos le corresponderá una entrada en el "omnis_modules.js" proporcionándose así la lista de métodos que podrán ser invocados desde Omnis.

Creación de un "Worker"


Asigne el subtipo del objeto externo "OW3 Worker Objects\JAVASCRIPTWorker", a una variable de tipo "Object" u "Object Reference", , también puede hacerse mediante crear una clase objeto a la que asignar el "subtipo" ya indicado, para luego asignarlo a una variable Omnis.

¡¡Importante!! Antes de invocar su método "$init", será necesario configurar su propiedad "$callbackinst", para indicar dónde recibir los resultados. Por ejemplo: "Calculate Object.$callbackinst as $cinst"

Propiedades


El "Worker JavaScript" soporta las propiedades "Worker" estándar: $state, $threadcount, $errorcode y $errortext.

Métodos de invocación


$init([cPath, bDebugNodeJs=kFalse])


Permite preparar el objeto, de forma que esté listo para ejecutar llamadas a métodos JavaScript. Devuelve "true" si tiene éxito. Debe ejecutarse antes que cualquier otro método.

  • cPath
    Permite cambiar la ruta de búsqueda de módulos predeterminada "NODE_PATH". La ruta predeterminada es "≤Carpeta de datos Omnis≥/node_modules". Tenga en cuenta, que sí cambia esta ruta, el resto de módulos que son obligatorios también deberán ser alojados en la nueva ruta.

  • bDebugNodeJs
    Booleano que indica si se desea poder depurar "node.js", por ejemplo, mediante Chrome. Es posible que no pueda iniciarse el "Worker" si se configura para más de un "Worker JavaScript" en activo, ya que "node.js" requiere de un puerto para depuración disponible. Para su depuración en Chrome, introduzca "chrome://inspect", y luego abra las herramientas de depuración dedicadas para "node.js". 

$start()


Ejecuta el "Worker JavaScript" en segundo plano. Devuelve "true" sí ha sido iniciado correctamente. El método $start(), se encargará de iniciar "node.js" he invocar los métodos JavaScript. Seguramente realizaremos llamadas a diferentes métodos del mismo proceso, por lo que no será necesario ejecutar $start() con frecuencia, lo que significa que la sobrecarga debida a la ejecución de procesos "node.js" es mínima.

$cancel


Cancela la ejecución del proceso "node.js". Cualquier método ya en progreso no será completado.


$callmethod(cModule, cMethod, vListOrRow [,bWait=kFalse, &cErrorText])



Permite la invocación de un método, al cual se pasa un solo parámetro desde el objeto JavaScript ("vListOrRow"). Opcionalmente se esperará a que el método complete su ejecución ("bWait"). El método devolverá "true" si la invocación es exitosa. "cModule" y "cMethod" identifican al módulo y al método dentro del módulo, que será invocado. "vListOrRow" será convertido a formato JSON antes de su paso al método como parámetro. El uso de "bWait" indicará que deseamos suspender la ejecución, hasta que el método haya terminado. "cErrorText" recibirá un texto descriptivo del error, en caso de fallo de "$callmethod".



Métodos de retorno




$cancelled


Se puede reescribir este método (Override) si se desea controlar la notificación correspondiente a una cancelación del "Worker" realizada correctamente.

$workererror(wError)


La reescritura de éste método (Override), permite recibir notificaciones de error del "Worker" no relacionados con la invocación a alguno de sus métodos, como, por ejemplo, un error producido al iniciarse "node.js". El sub-proceso del "Worker" se cerrará tras la generación de dicha notificación. "wError" contiene dos columnas, un entero llamado "errorCode" y un texto llamado "errorInfo".

$methoderror(wError)


La re-escritura de éste método (Override), permite recibir notificaciones de error tras el intento de invocar un método mediante "$callmethod". "wError" tiene dos columnas, un entero llamado "errorCode" y un texto llamada "errorInfo".

$methodreturn(wReturn)


Éste es el método al cual llegarán los resultados tras la ejecución de un "$callmethod". "wReturn" es una variable de tipo "row". Si el método de JavaScript devuelve un objeto, será el equivalente Omnis creado al convertir el JSON en una "row". Si el método de JavaScript devuelve otros datos, como por ejemplo. una imagen, esta consistirá en una "row" con una sola columna denominada "content", con los datos devueltos por el método.

26 de diciembre de 2018

El nuevo Depurador Remoto

La depuración remota permite depurar el código Omnis de una librería compartida en la red. Omnis usa para ello una versión “developer” independiente, el llamado “remote debug client”, el cual se conectará a través de la red a otro Omnis Studio, denominado “remote debug server”.


Algunos aspectos a tener en cuenta:

  • El “remote debug server” es quien ejecuta el código a depurar, y puede residir en cualquier tipo de instalación: “development”, “runtime”, “server” o “headless server”.
  • El código Omnis es ejecutado en modo “multi-threaded server”, creándose para ello pilas de procesos independientes de la principal.
  • El “remote debug server” y el “client” no precisan estar ejecutándose en el mismo sistema operativo.
  • La versión “client” debe ser la misma o posterior a la versión “server”.
  • Las clases protegidas y las bibliotecas bloqueadas también pueden ser depuradas.

Aunque hablamos de “depurador remoto”, en realidad, tanto el cliente como el servidor podrían residir en la misma máquina, de hecho cliente y servidor podrían contener los mismos procesos Omnis. En este último caso, el “remote debug client” es ejecutado con algunas restricciones, indicadas mas adelante en este artículo.

Conectividad


El “client” y el “server” se conectan entre sí a través de un WebSocket. Una conexión WebSocket es una conexión directa entre cliente y servidor, por lo que puede requerir de la apertura del puerto correspondiente en el “firewall”. Puesto que las conexiones WebSocket se inician como conexiones HTTP, un WebSocket puede soportar una conexión TLS segura, así como el requerimiento de un certificado de autenticación para el cliente. El “remote debug”, usa siempre una conexión TLS, por lo que el WebSocket es iniciado como HTTPS.

La conexión entre un cliente y un servidor es denominada “remote debug session” o simplemente “session”. Omnis podrá ejecutar una sola “session” a la vez.

El "Remote Debug Server"


Desde la versión “developer”, podremos configurar el “remote debug server” tras hacer clic sobre su nodo en el “Browser”, y seleccionar la opción “Remote Debug Server”.

Para una versión “runtime” de Omnis (no “headless”), y si la librería “remotedebug.lbs” está en la carpeta “startup”, se dispondrá de un menú denominado “Remote Debug”. El cual contiene una sola opción, que permite abrir la ventana de configuración. Si se trata de un servidor “headless” podremos llevar a cabo la configuración desde la ventana de administració (osadmin).

La ventana de configuración muestra dos pestañas, una para controlar el servidor y otra para configurarlo.

La pestaña “Control Server” tiene un solo botón, utilizado para arrancar o detener el servidor. De no encontrarse arrancado, no aceptará conexiones desde un cliente.

La pestaña “Configure Server” permite llevar a cabo su configuración, muestra los campos que corresponden a las entradas en el archivo de configuración y que describiremos a continuación.

El fichero de configuración


La configuración se guarda en el fichero denominado  “remote_debug_server_config.json”, ubicado en “clientserver/server/remotedebug” de la carpeta de instalación Omnis. Podemos optar por editar este archivo JSON directamente con cualquier editor o usar la opción descrita anteriormente.

Debemos tener en cuenta que Omnis hace uso de un servidor “node.js” ejecutado junto con Omnis, desde el se construye el servidor WebSocket. Como consecuencia, parte de la información de configuración es compartida también con “node.js”.

Configuración ejemplo:

{
   "debugPort": 8080, 
  "serverPfx": "server.pfx", 
  "pfxPassPhrase": "xxxxxx", 
   "ca": [ "server_cert.pem" ], 
  "requestCert": false, 
  "rejectUnauthorized":  false, 
  "userName": "myUser",
 "hashedPassword":   
 "AAGGoAAAABBSEkknQUIeHQHu1sIyWxlSAAAAIHw9kvCVF4tE//S   MpbSGVD/RKJLekoR7TlTvZVy3MbkJ", 
   "startRemoteDebugServerAtStartup": true,
   "pauseAtStartupUntilDebuggerClientStartsExecution": false,
   "logConnectionSetup": false
}

debugPort

El puerto TCP/IP en el que el servidor WebSocket escucha las conexiones entrantes desde el cliente.

serverPfx

Este es un archivo que contiene el certificado del servidor y la clave privada. Debe estar en el mismo directorio que el “remote_debug_server_config.json”. La instalación por defecto consta de un certificado auto-firmado y una clave generada mediante el comando openssl (disponible en cualquier sistema con openssl instalado). Tendrá que proporcionar su propia clave privada y su certificado. Puede generar una nueva clave privada y un certificado auto-firmado utilizando los siguientes comandos:

openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -nodes -days 1024 -subj "/CN=localhost/O=Demo" -passin pass:xxxxxx
openssl pkcs12 -export -out server.pfx -inkey server_key.pem -in server_cert.pem

Este archivo deberá ser indicado bajo la opción “PFX” y es invocado por el método https.createServer() de “node.js”. Podrá encontrar más información sobre esto, en la documentación de “node.js”:

https://nodejs.org/docs/latest-v8.x/api/https.html#https_class_https_serve 
https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options

pfxPassPhrase

Esta es la frase-contraseña utilizada para proteger el archivo PFX en el servidor. En nuestro ejemplo es "xxxxxx".

ca

Ver https://nodejs.org/docs/latest-v8.x/api/tls.html#tls_tls_createsecurecontext_options para más detalles. Normalmente, usted sólo tendrá un CA, puesto que tiene un sólo certificado auto-firmado, en cuyo caso tendremos una sola entrada. En nuestro ejemplo el certificado fue firmado usando “server_cert.pem”. Generalmente su valor es una lista separada por comas de certificados de confianza, nombres de archivos los cuales deben residir en el mismo directorio que el “remote_debug_server_config.json”.

requestCert

Valor booleano. Si es verdadero, el servidor “node.js” solicitará un certificado para autenticar al cliente. Los certificados de cliente se explican más adelante, en la entrada conectividad del cliente.

rejectUnauthorized

Valor booleano. Si es verdadero, el servidor rechazará cualquier conexión no incluida en la lista de CA’s suministrada. Esta opción solo tiene efecto si “requestCert” es cierto.

userName

Si no está vacío, la conexión WebSocket también usará autenticación básica HTTP con el usuario, en cuyo caso este campo deberá contener el nombre del usuario utilizado para la autenticación básica HTTP.

hashedPassword

Si “userName” no está vacío, será el "hash" PBKDF2 de la contraseña requerida para la autenticación básica HTTP.

startRemoteDebugServerAtStartup

Esta opción booleana indica si el “remote debug server” debe iniciarse  automáticamente al iniciarse Omnis.

pauseAtStartupUntilDebuggerClientStartsExecution

Si el “remote debug server” está configurado para iniciarse automáticamente cuando se inicia Omnis, podremos configurar esta opción booleana a “true” para causar que Omnis pause su ejecución durante el momento de ejecutar la “startup_task” y otras "tasa" iniciales de nuestra librería Omnis.

Cuando se utiliza esta opción, Omnis muestra un mensaje de trabajo (Waiting for remote debug client to start execution…), entrando en un bucle de espera, hasta que se reciba un comando desde el cliente para ejecución. Durante este bucle, el cliente podrá ver y depurar el código remotamente, mediante (por ejemplo) establecer puntos de interrupción.

El bucle termina cuando el cliente envía un comando de inicio de ejecución, cuando la sesión con el “remote debug server” es cerrada o cuando un usuario hace clic sobre el botón “cancel” situado junto al mensaje de trabajo mostrado en el servidor. Cuando el bucle termina, Omnis ejecutará la “startup_task” de la librería.

El “Remote Debug Client”


El “remote debug client” es accesible a través de un nuevo nodo situado sobre el árbol del navegador de Studio denominado, "Remote Debug Client". Utiliza un modelo de sesión similar al de VCS. Tras hacer clic sobre el nodo, se mostrarán los enlaces “Session Manager”, y “Open Session”.

El “Session Manager” permite configurar las sesiones de depuración remotas. Cada sesión contendrá los parámetros que permitirá al cliente iniciar un WebSocket de conexión con un “remote debug server”. A continuación describimos cada uno de sus parámetros:

Name

Nombre que identifica el sesión.

Server

Dirección IP o nombre DNS del “remote debug server”.

Debug Port

Puerto configurado en el “remote debug server”. En su conexión al servidor, el cliente construirá la URL siguiente:
wss://Server:DebugPort

Client Certificate

Si el servidor requiere un certificado de cliente, deberá especificarse aquí. Podrá generar un certificado de cliente usando los siguientes comandos openssl:
openssl req -newkey rsa:4096 -keyout client_key.pem -out client_csr.pem -nodes -days 1024 -subj "/CN=192.168.1.11" -passin pass:xxxxxx
openssl x509 -req -in client_csr.pem -CA server_cert.pem -CAkey server_key.pem -out client_cert.pem -set_serial 01 -days 1024
Tenga en cuenta que en este ejemplo usamos la clave y el certificado de servidor utilizados con el ejemplo para el “PFX”. Paro, el certificado del cliente necesitará ser instalado en la máquina del cliente.

Para Windows, genere un archivo “client.pfx”:
openssl pkcs12 -export -out client.pfx -inkey client_key.pem -in client_cert.pem
Añada el “client.pfx” al almacén de certificados de Windows, mediante hacer doble clic  en el archivo, agregándolo a “Personal certificates” del usuario en curso.

Para macOS, genere un archivo “pkcs12”:
openssl pkcs12 -export -out client.p12 -inkey client_key.pem -in client_cert.pem
Haga doble clic sobre el archivo para agregarlo al llavero.
Puede encontrar más detalles sobre esto en la documentación sobre CURL en:
https://curl.haxx.se/libcurl/c/CURLOPT_SSLCERT.html
Tenga en cuenta que el parámetro “Client Certificate” pasa su valor al comando CURL bajo la opción CURLOPT_SSLCERT.

En caso de Windows, el parámetro es la ruta hacia el lugar donde está almacenado…
CurrentUser\MY\afe2179599460d20da08c12e8c328d84bd300735
…donde afe2179599460d20da08c12e8c328d84bd300735 es la huella digital, visible mediante hacer doble clic en “certificate” del MMC (MMC certificate snap-in view, pestaña “details”, campo “thumbprint”).

En caso de macOS, se puede especificar la ruta del archivo “p12” o el nombre que tiene en el llavero del cliente.

User Name

Si el servidor utiliza autenticación básica HTTP, es el nombre de usuario requerido.

Password

Si el servidor usa autenticación básica HTTP, será la contraseña requerida.  Alternativamente, podrá dejarse vacía, causando que se le solicite al cliente la cuando sea necesaria.

Server Connection Logging

Mediante ésta opción podremos monitorizar la conexión con el “remote debug server”, para poder observar cualquier problema de conexión. También deberemos habilitar ésta opción en el archivo de configuración, bajo la entrada “logConnectionSetup”.

Si está habilitado, se creará un archivo de registro  denominado: “.htm” en el directorio “logs/remotedebug , con el registro de lo que ha ocurrido al conectarse al “remote debug server”. Tenga en cuenta que el registro no se escribe hasta que la conexión es cerrada.

Preparación del código para su depuración remota


Deberemos habilitar en nuestras librerías e instancias de tipo tarea “task” la capacidad “remote debugging” mediante configurar su propiedad $remotedebug.

Library


Por defecto, una librería no puede ser depurada remotamente, lo que significa que cuando el cliente intente conectarse para depuración, normalmente no aparecerá en el interfaz de cliente. Si queremos que aparezca necesitaremos establecer su propiedad “$clib.$remotedebug”, como “True”, lo cual no podrá realizarse sobre librerías ya marcadas como privadas, lo que significa que deberemos fijar esta propiedad como “true” antes de hacerla privada.

Task


La configuración de “$clib.$remotedebug” permite que la librería y sus clases aparezcan sobre la ventana cliente de depuración remota. Permitiéndonos manipular su código y establecer “break points”.

Sin embargo, sólo las clases “task” y “remote task” marcadas para depuración remota, reaccionarán ante los “breack points” que fijemos. Esto permitirá un mayor control sobre lo que podrá o no podrá ser depurado remotamente y del lado del servidor, permitirá evitar que un “breack point” detenga la ejecución para otros posibles clientes en uso.

Para marcar una “task” o “remote task” para depuración remota, configure su propiedad
“$remotedebug” a kTrue.

Tabién podremos activar ésta propiedad, cómo un parámetro en el URL de conexión, hacia un “remote form” (omnisRemoteDebug = 1), por ejemplo:
http://127.0.0.1:5981/jschtml/jsDragDrop.htm?omnisRemoteDebug=1

Interfaz del depurador remoto 

Abriendo un sesión

Para usar el “remote debugger client” tras configurar una sesión, haga clic sobre el nodo “Remote Debug Client” y después sobre el enlace “Open Session”, luego haga clic sobre el enlace correspondiente a la sesión que deseemos utilizar.

Esto hará que el cliente inicie una conexión WebSocket con el servidor. Mientras se establece, se mostrará su progreso sobre el panel del navegador, aunque suele ser muy rápido. Además, aparecerá un nuevo enlace durante éste proceso denominado “Cancel Open Session”.

Browsing Libraries

Una vez abierta la sesión, se mostrarán las bibliotecas marcadas para depuración remota.

Los nodos secundarios del “Remote Debug Client” tienen un comportamiento similar al de los habituales para la edición de librerías. Cuando seleccionamos alguno de éstos nodos secundarios, el panel del navegador se actualizará para mostrar su contenido permitiendo la edición de todo el contenido de la librería.

Si se selecciona una sola clase en el panel del navegador, se mostrará un enlace denominado "Open debug window". Haga clic sobre él para abrir la ventana de depuración remota para esa clase.

Finalmente, si el servidor está en pausa y por tanto a la espera de ejecutar el inicio, entre los enlaces podrá ver uno con el nombre “Run Startup”, mediante el cual podrá indicar al servidor que debe continuar y ejecutar su proceso inicial.

La ventana del “Remote Debug”

Esta ventana muestran un diseño muy similar al del editor de métodos. Su diferencia principal está en que siempre muestra el panel de depuración y no existe un panel de edición, y en su esquina inferior derecha aparece un nuevo panel de variables.

La barra de herramientas (Instance)

Permite mostrar los métodos u objetos específicos de una instancia actualmente en uso. El menú “Instance” nos permitirá cerrarla, así como también retirarla o añadirla a la lista del depurador.

Tenga en cuenta que este menú se desactiva tan pronto como la ventana de depuración remota es asociada, es decir durante el proceso de depuración de una instancia.

Observaciones

Deberemos tener presente que el conjunto de librerías e instancias, susceptibles de ser depuradas pueden cambiar en el servidor. Omnis mantiene al cliente constantemente actualizado con respecto a la situación en que se encuentre el servidor. Por ejemplo, si una librería se cierra en el servidor, se informa al cliente y se actualiza su interfaz lo que significa su eliminación del navegador y el cierre de cualquier ventana de depuración remota relacionada. Sin embargo, si se producen cambios en un método en el servidor, el cliente no recibirá el método actualizado hasta que sea de nuevo solicitado, debe tenerse en cuenta que cada vez que el cliente realiza una operación de depuración, el cliente solicita el método y retiene una copia del mismo, hasta que la acción termina, si durante ese proceso, el método ha cambiado en el servidor, el cliente no lo recibirá hasta necesitar una nueva copia.


25 de diciembre de 2018

Omnis Developers Conference, Mexico City – Lunes 11 de Marzo 2019

Lunes 11 de Marzo 2019,  Omnis Developers Conference, Mexico City

Martes 12 + Miercoles 13 Marzo 2019,  Omnis Academy, Mexico City
Objetivos
  • Conocer OMNIS Studio
  • Presentar de la nueva versión 10
  • Componer aplicaciones que traspasan las fronteras
  • Componer aplicaciones Web y Moviles (Android, iOS, Windows 10)
  • Establecer contactos, conociendo más detalle sobre aplicaciones y proyectos.

Consulte la agenda e inscríbase hoy mismo...

2 de noviembre de 2018

¡El anuncio anticipado de un punto de viraje en la ya larga historia de Omnis!

Esta entrada en el blog, no es para describiros una característica de Omnis Studio, ni para (como os tengo acostumbrados) arrojar nueva luz sobre como hacer las cosas con ésta magnífica herramienta, simplemente es que no me he podido resistir a perder la ocasión de hacerme eco del más que interesante anuncio que Omnis a hecho el pasado 1 de Noviembre del 2018.

Sin duda y como reza en el título de ésta entrada, marcará una "antes-y-después" en la historia de Omnis Studio. Será muy emocionante ir descubriendo las novedades que nos esperan.



1 de octubre de 2018

Accesibilidad WCAG 2.0 con Omnis Studio

Otra de las novedades de la nueva versión 9 de Omnis Studio. permitirá dar soporte en nuestras aplicaciones Web, a las llamadas "Pautas de Accesibilidad para el Contenido Web" (WCAG 2.0) lo cual permitirá que éstas sean más accesibles, principalmente para personas con discapacidades. Estas directrices han sido adoptadas por muchas agencias gubernamentales y garantizan un nivel aceptable de acceso a la información y los servicios proporcionados por los sitios web a personas con diferentes discapacidades. Puede leer las siguientes páginas para obtener una comprensión básica de los requisitos de WCAG:

https://www.w3.org/WAI/standards-guidelines/



La implementación de WCAG en Omnis Studio hace referencia a la especificación ARIA, (Accessible Rich Internet Applications) la cual describe una forma de hacer que el tanto el contenido web, como las aplicaciones para la web, sean más accesibles para las personas con discapacidades. Especialmente hace hincapié en el contenido dinámico y los controles avanzados del interfaz de usuario, lo cual tiene un amplio soporte en la tecnología jsClient desarrollada por Omnis Studio.

En la práctica, esto significa que hemos agregado varias propiedades compatibles con ARIA a los controles JavaScript, tanto para la web como para las aplicaciones móviles, pensando siempre en los usuarios con discapacidades. Estas propiedades serán activadas automáticamente, cuando las propiedades del dispositivo estén habilitadas, bien sea en el navegador o en el móvil del usuario.

4 de julio de 2018

¿Que habrá en Omnis Studio 9?

En la conferencia "Omnis Developer" celebrada en mayo de este año en Alemania, Bob Mitchell, (Omnis Engineering Manager) desveló algunas de las características que podremos ver en el futuro Omnis Studio 9. De todas ellas, con seguridad la más atrayente es su totalmente renovado editor de código, realmente un paso esperado por la comunidad de desarrolladores y que hace de Omnis Studio una herramienta aún más rápida y eficaz en el desarrollo de aplicaciones web y dispositivos móviles.

En su exposición (disponible en YouTube) Bob describe los cambios de sintaxis, que también se introducen junto con la entrada del nuevo editor de código Omnis.


El nuevo editor reemplazará al actual de disposición en lista, ampliando las opciones del actual "Code Assistant". La escritura de código se realiza al estilo de un editor de texto convencional, pero cuando es necesario, el "Code Assistant" hace su aparición de forma totalmente automática ayudándonos a completar expresiones, nombres, opciones y parámetros de los comandos. No obstante y en cualquier momento, se puede presionar Ctrl-espacio para abrir el asistente de código y obtener así ayuda relativa al contexto, incluso con una descripción completa del comando y ejemplos de uso.

A continuación enumeramos algunas de sus características:

  1. Diseño rígido (el código aún se guarda de forma codificada)
  2. Utiliza una fuente de ancho fijo.
  3. Aumento de la capacidad de "deshacer" y "rehacer" (disponible también desde otros ámbitos del futuro Omnis Studio 9)
  4. Coloración de sintaxis: nuevos colores para indicar el alcance de las variables, opciones de comandos, funciones, etc.
  5. Las construcciones de comandos con cierres se auto-completan, por ejemplo, al escribir "If" se añade automáticamente el "End If".
  6. El panel de ayuda muestra tanto su sintaxis, como una descripción completa del comando.
  7. Los errores en el código, son marcados mediante un subrayado rizado.
  8. Diferentes opciones seleccionables desde la paleta situada en la parte superior del editor, permiten obtener ayuda sobre parámetros así como la localización y corrección de errores, entre otras muchas funciones.
  9. Permite la declaración de variables con ámbito y tipo automático indicado por medio de prefijos y sufijos, por ejemplo, "iVarList" será una variable de instancia (prefijo "i") de tipo "list" (sufijo "List").
  10. Nuevas opciones tales como, "Goto line number", "Select line", "Upper/Lower case", triple-clic para seleccionar una línea de código para (por ejemplo) eliminarla y búsqueda por palabras, entre otras.
  11. Una nueva propiedad denominada "$keys" que funciona en conjunción con un fichero de nombre "keys.json", permite configurar y guardar todos los atajos de teclado que queramos usar con éste nuevo y magnífico editor de código Omnis.

Otras características y disponibilidad:

Bob también nos hablo sobre algunas otras cosas que se espera incluirá Omnis Studio 9, "Remote Objects" los cuales podrán contener métodos de ejecución exclusiva en el cliente, "Omnis Datafile Migration", una herramienta para la conversión automática de archivos ".df1" a SQLite o PostgreSQL, soporte para los estándares de accesibilidad en la Web (WCAG 2.0), "Remote Debugging" el cual nos permitirá depurar nuestras aplicaciones para la web y dispositivos móviles de modo más cómodo y eficaz, nuevos controles JavaScript, entre ellos el denominado "iCalendar"".

La primera versión Beta de Omnis Studio 9, estará disponible para los desarrolladores a finales de año.

2 de julio de 2018

Uso del método "$pushdata"

Para dar soporte a las notificaciones "push", disponemos de un nuevo método para instancias "remote form" denominado $pushdata(), con la siguiente sintaxis:

$pushdata(wRow[~&cErrorText])

Usado en conjunción con $clientcommand("openpush";row()). El método provoca una llamada al método $pushed de la instancia "remote form" del cliente, pasando "wRow" como parámetro, su formato debe ser compatible JSON, por lo que solo puede contener tipos:

"character", "boolean", "integer", "number", "date", "list" o "row".

Omnis mantendrá encolados los datos enviados desde cada "remote task", independiente de las llamadas "openpush" que tenga asociadas. Tan pronto como llega una petición "push" de un cliente, Omnis envía los datos a la cola, para que el cliente la procese cuando esté disponible.

Cuando el cliente procesa la respuesta se emite una nueva petición "push", indicándole al servidor que recibió los datos. Esto permite al servidor eliminar de la cola, los elementos de datos ya procesados liberando memoria. La conexión permanece abierta y tan pronto como desde del servidor se ordena la ejecución de "$pushdata", Omnis envía los datos al cliente, puede dar la impresión de que existiese una conexión permanente entre servidor y cliente, pero no es así, sino que simplemente se establece un control de datos enviados y recibidos por los clientes, evitando pérdidas.

La práctica habitual sera que los clientes guarden la información entregada por "$pushdata" en una variable o en subconjunto de variables de ambito instancia, para actualizar su "remote form".

29 de enero de 2018

Obtener el UUID de la sesión Omnis Studio Web

Entre las muchas cosas que incorporó la versión 8.1 de Omnis Studio para la Web, nos contaba los chico de Omnis, que ahora al establecerse la comunicación desde el cliente con el servidor de aplicaciones web, se genera un UUID de identificación para la sesión, el cual es guardado como una cookie y enviada como parámetro cada vez que se produce un intercambio de datos. La cookie caduca después de un año, tras el cual, se generará un nuevo UUID. Naturalmente las cookies deberán estar habilitadas, tanto en el servidor web, como en los clientes para que esto funcione.



Nada mas leer esto me preguntaba cómo podríamos desde programación Omnis, obtener el UUID asignado y así poder usarlo, para (por ejemplo) guardar y ajustar preferencias relativas a la sesión en uso, la respuesta viene de la mano de javascript, ya sabemos que podemos incluir código javascript, en los métodos de ejecución exclusiva en el cliente, habitualmente usamos el método "$init" en nuestros "remote-form" con éste propósito, a continuación mostramos el código necesario para la obtención del UUID asignado a la sesión:

JavaScript: var getCookie = function (name) {
JavaScript: {    var cookies = document.cookie.split(';');}
JavaScript: {    for (var i = 0 ; i < cookies.length ; ++i) {}
JavaScript: {        var pair = cookies[i].trim().split('=');}
JavaScript: {        if (pair[0] == name) return pair[1];}
JavaScript: {    }}
JavaScript: {    return NULL;}
JavaScript: }
JavaScript: lIDCookie = getCookie("OMNISCLIENTID");
Do method setIDCookie (lIDCookie)
"lIdCookie" es una variable local y "setIDCookie" es el método (de ejecución en el servidor) que recibirá "lIDCookie" como parámetro.



22 de enero de 2018

Aplicar CSS a las líneas de un pop-menu en Omnis Studio Web

Aún existen esos "tipos raros" que dedican su tiempo libre a investigar como hacer ciertas cosas en programación con Omnis Studio, el reto que me plantee consistía en como conseguir espaciar las líneas que componen un pop-menú en Omnis Studio para la Web, la siguiente imagen describe lo que se pretende conseguir:


Haciendo un poco de investigación, se puede observar que omnis monta una tabla (etiqueta html ≤table≥) a la que asigna un nombre de clase (atributo class) compuesta del siguiente modo: [nombre-del-remoteform]_[id-del-objeto-pop-menu]_clientTable de modo que lo que hice fue incluir un identificador de clase y algunos atributos CSS en el documento "user.css" que Omnis suministra al efecto.

Ejemplo:


.RemoteForm_1001_clientTable {
border-collapse: separate;
border-spacing: 0px 10px;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
}

En el ejemplo, he añadido algo de separación  entre el primero y último elemento del grupo. Les animo a que prueben variantes del código expuesto adaptándolo a sus necesidades.

Otra variante de este CSS podría ser lo siguiente...

.RemoteForm_1001_clientTable td {
     height: 31px; 
}

...esto modificará únicamente las líneas del menú cambian su altura y por tanto también el espacio entre ellas, éste último caso es el que más me gusta y que uso habitualmente para mis menús.

NOTA: Creo que los ingenieros de Omnis se han hecho eco de éste artículo, pues en la versión 8.1.6, ya se incluyen nombres de clases CSS para poder realizar éste tipo de cambios más facilmente, para el caso que nos ocupa, sería cambiar ".RemoteForm_1001_clientTable" por ".omnis-menu-table", de éste modo funcionará para con todos los menús de nuestra aplicación.


18 de enero de 2018

Notificaciones y diálogos con AppleScript y Omnis Studio 8.1


En esta entrada del blog, quisiera exponer un pequeño ejemplo sobre cómo enviar notificaciones y diálogos al sistema macos, las notificaciones pueden resultar muy útiles, pues permiten enviar mensajes al usuario si esperar a que sean aceptados por éste, por otra parte, los diálogos del sistema mantendrá en suspenso la ejecución de Omnis hasta la aceptación del mismo por parte del usuario, pero salva las limitaciones en cuanto a longitud del texto a mostrar en el mismo.

A continuación un ejemplo de cada caso:

Método: $notificacion

Begin text block
Text: {display notification "Una notificación: Hola"}
End text block
Get text block lScript
Do $runapplescript(lScript;lResultado;lError)

Método: $dialogo

Begin text block
Text: {display dialog "Un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa,un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa, un texto my largo donde quiero explicar todo lo que hace éste programa." buttons {"Aceptar"} default button "Aceptar"}
End text block
Get text block lScript
Do $runapplescript(lScript;lResultado;lError)

Saludos cordiales a todos los seguidores de éste blog.


24 de diciembre de 2017

Comunicaciones seguras con Omnis Studio

Otra importante característica de la versión 8 de Omnis Studio, es la eliminación de la dependencias con OpenSSL como único medio para dotar de soporte a comunicaciones seguras. Como ya sabemos Omnis Studio aporta una buen catálogo de comandos Web con los que realizar éste tipo de conexiones, los denominados: FTPConnect, HTTPOpen, TCPConnect, POP3Connect, SMTPSend, etc.

El haberse eliminado las antiguas dependencias con OpenSSL, ahora ya no será necesaria su instalación adicional en aquellas plataformas donde no se incluía de serie, en su lugar, se usa la tecnología, que de forma predeterminada incorpora cada plataforma, de modo que en el caso de Windows se usa 'Secure Channel' (Schannel), en macOS se usa 'Secure Transport' y sólo en caso de Linux, se seguirá usando OpenSSL ya que es su tecnología de seguridad predeterminada.

No obstante, quisiera recordar en éste artículo, los pasos a seguir cuando (al usar versiones anteriores de Omnis Studio) necesitamos instalar OpenSSL en plataformas Windows, para su uso con Omnis Studio.

Primero recordamos cuales son las librerías que dan soporte a éstos comandos y que podremos hallar bajo el directorio de instalación de Omnis Studio, las denominadas:

  • wesecure.dll que añade una capa de funcionalidad entre weshared y OpenSSL
  • weshared.dll que da soporte a los comandos Web

Ahora lo que necesitaremos es incorporar a éste mismo directorio las librerías libeay32.dll y ssleay32.dll, las cuales podremos obtener de forma gratuita en internet, seleccionando la correspondiente a nuestra plataforma, por ejemplo, desde la web de "embarcadero" que nos facilita su instalación en: http://docwiki.embarcadero.com/RADStudio/Tokyo/en/OpenSSL

Por último deberemos asegurarnos de que también este presente la carpeta o directorio, incluido con Omnis Studio denominado "secure". Omnis Studio usa las "Autoridades de Certificación" instaladas en el subdirectorio denominado "cacerts" del directorio "secure". Si usa su propia "Autoridad de Certificación" para auto-firmar certificados, deberá incluirá en ésta misma carpeta, Omnis la usará tras ser reiniciado.





14 de diciembre de 2017

Android Studio vs Omnis Studio

En éste artículo quiero comparar lo que supone crear una aplicación sencilla para un dispositivo Android, con dos diferentes herramientas para el desarrollo de "App's": Android Studio (exclusiva de la plataforma y gratuita) y Omnis Studio (multi-plataforma y de pago). Queremos que la aplicación sea capaz de crear una base de datos SQLite en el dispositivo, con tres campos: ID, Nombre y Apellido y cuatro botones para iteracción con el usuario: "Buscar", "Insertar", "Actualizar" y "Borrar", su aspecto y código necesarios se muestran a continuación:

Aspecto con Android Studio

Aspecto con Omnis Studio

Para añadir los elementos de la "interface" en ambos casos sólo ha sido necesario arrastrar y soltar componentes desde sus respectivas paletas, pero a la hora de girar el dispositivo, "Android Studio" a requerido programación adicional, mientras que con "Omnis Studio" no ha sido necesario incluir programación alguna.

A continuación indicaremos el código que ha sido necesario escribir en cada caso, empezando por la creación de la BBDD SQLite en el dispositivo:

Creación de la BBDD en Android Studio

public class Estructura_BBDD {

private Estructura_BBDD() {}

        public static final String TABLE_NAME = "datosPersonales";
        public static final String NOMBRE_COLUMNA1 = "id";
        public static final String NOMBRE_COLUMNA2 = "nombre";
        public static final String NOMBRE_COLUMNA3 = "apellido";

    public static final String SQL_CREATE_ENTRIES =
            "CREATE TABLE " + Estructura_BBDD.TABLE_NAME + " (" +
                    Estructura_BBDD.NOMBRE_COLUMNA1 + " INTEGER PRIMARY KEY," +
                    Estructura_BBDD.NOMBRE_COLUMNA2 + " TEXT," +
                    Estructura_BBDD.NOMBRE_COLUMNA3 + " TEXT)";

    public static final String SQL_DELETE_ENTRIES =
            "DROP TABLE IF EXISTS " + Estructura_BBDD.TABLE_NAME;
}

Creación de la BBDD en Omnis Studio

Do $cinst.$sqlobject.$execute('CREATE TABLE Empleados (Id INTEGER UNIQUE, Nombre TEXT, Apellido TEXT)')
      Returns IDcreatetable

Un apunte antes de continuar en cuanto a la programación asociada a cada botón, en el caso de "Andriod Studio" ha sido necesario añadir código adicional para poner los botones en modo "OnClickListener", cosa totalmente innecesaria en "Omnis Studio", salvando ésta diferencia, (no trivial) indicamos el asociado a cada botón:

Botón "Buscar" en Android Studio

botonBuscar.setOnClickListener(new View.OnClickListener() {
   @Override   public void onClick(View v) {
       SQLiteDatabase db = helper.getReadableDatabase();
       String[] projection = {
               Estructura_BBDD.NOMBRE_COLUMNA2,
               Estructura_BBDD.NOMBRE_COLUMNA3       };

       String selection = Estructura_BBDD.NOMBRE_COLUMNA1 + " = ?";
       String[] selectionArgs = { textoId.getText().toString() };

       try {
           Cursor c = db.query(
                   Estructura_BBDD.TABLE_NAME,         
                   projection,                         
                   selection,                          
                   selectionArgs,                      
                   null,                               
                   null,                               
                   null                                
           );

           c.moveToFirst();
           textoNombre.setText(c.getString(0));
           textoApellido.setText(c.getString(1));

       }catch (Exception e){
           Toast.makeText(getApplicationContext(),"No se han encontrado registros.", Toast.LENGTH_LONG).show();
       }
   }
});

Botón "Buscar" en Omnis Studio

On evClick
Do lRow.$define(i_ID;i_Nombre;i_Apellido)
Do lRow.$assigncols(i_ID;i_Nombre;i_Apellido)
Do $cinst.$sqlobject.$selectfetch("Select * from Empleados where Id = @[i_ID]";lRow;kFetchAll) 
              Returns IDselectfetch

Botón "Insertar" en Android Studio

botonInsertar.setOnClickListener(new View.OnClickListener() {
    @Override    public void onClick(View v) {
        SQLiteDatabase db = helper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(Estructura_BBDD.NOMBRE_COLUMNA1, textoId.getText().toString());
        values.put(Estructura_BBDD.NOMBRE_COLUMNA2, textoNombre.getText().toString());
        values.put(Estructura_BBDD.NOMBRE_COLUMNA3, textoApellido.getText().toString());

        long newRowId = db.insert(Estructura_BBDD.TABLE_NAME, null, values);
        Toast.makeText(getApplicationContext(),"Insertado ID: " + newRowId, Toast.LENGTH_LONG).show();
    }
});

Botón "Insertar" en Omnis Studio

On evClick
Do lRow.$define(i_ID;i_Nombre;i_Apellido)
Do lRow.$assigncols(i_ID;i_Nombre;i_Apellido)
Do $cinst.$sqlobject.$insert("INSERT INTO Empleados (Id, Nombre, Apellido) VALUES (@[i_ID],@[i_Nombre],@[i_Apellido])";lRow)
             Returns IDinsert

Botón "Actualizar" en Android Studio

botonActualizar.setOnClickListener(new View.OnClickListener() {
    @Override    public void onClick(View v) {

        SQLiteDatabase db = helper.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(Estructura_BBDD.NOMBRE_COLUMNA2, textoNombre.getText().toString());
        values.put(Estructura_BBDD.NOMBRE_COLUMNA3, textoApellido.getText().toString());

        String selection = Estructura_BBDD.NOMBRE_COLUMNA1 + " LIKE ?";
        String[] selectionArgs = { textoId.getText().toString() };

        int count = db.update(
                Estructura_BBDD.TABLE_NAME,
                values,
                selection,
                selectionArgs);
        Toast.makeText(getApplicationContext(),"Registro actualizado.", Toast.LENGTH_LONG).show();
    }
});

Botón "Actualizar" en Omnis Studio

On evClick
Do lRow.$define(i_ID;i_Nombre;i_Apellido)
Do lRow.$assigncols(i_ID;i_Nombre;i_Apellido)
Do $cinst.$sqlobject.$update("UPDATE Empleados SET Nombre=@[i_Nombre], Apellido=@[i_Apellido] where Id = @[i_ID]";lRow;lRow)
              Returns IDupdate

Botón "Borrar" en Android Studio

botonBorrar.setOnClickListener(new View.OnClickListener() {
    @Override    public void onClick(View v) {

        SQLiteDatabase db = helper.getWritableDatabase();
        String selection = Estructura_BBDD.NOMBRE_COLUMNA1 + " LIKE ?";
        String[] selectionArgs = { textoId.getText().toString() };
        db.delete(Estructura_BBDD.TABLE_NAME, selection, selectionArgs);
        Toast.makeText(getApplicationContext(),"Registro borrado.", Toast.LENGTH_LONG).show();
        textoId.setText("");
        textoNombre.setText("");
        textoApellido.setText("");
    }
});

Botón "Borrar" en Omnis Studio

On evClick
Do lRow.$define(i_ID;i_Nombre;i_Apellido)
Do lRow.$assigncols(i_ID;i_Nombre;i_Apellido)
Do $cinst.$sqlobject.$delete("DELETE FROM Empleados WHERE Id = @[i_ID]";lRow)
              Returns IDdelete

Notemos que en el código Android se ha evitado deliberadamente la incorporación del código necesario para tratar las excepciones, salvo en el caso del botón "Buscar" donde se usa un "try-catch", para controlar el hecho que pueda no encontrarse el registro buscado. Omnis predefine un método para tratar las excepciones denominado "$sqldone", a continuación mostramos un ejemplo de uso:

;  Se ejecuta cada vez que concluye una operación SQL (asíncrona)
;  Abandona el método con el mensaje de error, si se produce.

Do $cinst.$sqlobject.$getlasterrortext() Returns lErr
If lErr<>"OK"
Calculate i_ID as 0
Calculate i_Nombre as ''
Calculate i_Apellido as ''
Do $cinst.$showmessage(lErr;"Error")
Quit method
End If

;  Se ejecuta uno u otro proceso según el resultado
Switch pID
Case IDselecttables
If pResult.$linecount=0
Do $cinst.$creaTabla()     ;; Si no existe se crea la tabla
End If
Case IDselectfetch
Calculate lRows as pResult.$linecount
If lRows=0
Calculate i_ID as 0
Calculate i_Nombre as ''
Calculate i_Apellido as ''
Do $cinst.$showmessage("No existe el ID";"Respuesta")
Quit method
End If
Calculate i_Nombre as pResult.C2
Calculate i_Apellido as pResult.C3
Case IDcreatetable
Do $cinst.$showmessage("Tabla creada";"Respuesta")
Case IDinsert
Do $cinst.$showmessage("Inserción realizada";"Respuesta")
Case IDdelete
Calculate i_ID as 0
Calculate i_Nombre as ''
Calculate i_Apellido as ''
Do $cinst.$showmessage("Entrada borrada";"Respuesta")
Case IDupdate
Do $cinst.$showmessage("Actualización realizada";"Respuesta")
Default
Calculate i_ID as 0
Calculate i_Nombre as ''
Calculate i_Apellido as ''
Do $cinst.$showmessage("Error inesperado")
End Switch

En ocasiones los programadores y compañías dedicadas al desarrollo y mantenimiento de software, nos preguntamos ¿Porqué pagar por una herramienta, cuando existe otra que es gratis?, pero definitivamente puedo decir que en muchas ocasiones lo "barato" sale caro. Omnis Studio permite el desarrollo de aplicaciones para dispositivos móviles (Android, iOS y Windows), aplicaciones de escritorio (MacOS, Windows, Linux) o aplicaciones para la Web, sin necesidad de usar más herramientas que el propio Omnis Studio. El ejemplo de eficacia que hemos expuesto, compara una herramienta que sólo permite el desarrollo para dispositivos Android, por lo que el código resultante no podrá ser ejecutado en (por ejemplo) un dispositivo iOS, en cambio el código Omnis, puede ser ejecutado sin cambio alguno, sobre dispositivos iOS o Windows 10.

Juzguen ustedes mismos sobre si lo "barato" sale caro, llevo trabajando con Omnis Studio por unos 20 años ya, período durante el que las tecnologías han sufrido muchos y diferentes cambios que han hecho, al mismo tiempo, aparecer y desaparecer lenguajes de programación, pero Omnis Studio a sabido adaptarse a los tiempos y a tiempo con gran lujo y esmero.

Programar con Omnis Studio hace que me guste éste trabajo.