1403xe5iberianTour

Desarrollo móvil y web con Rad Studio XE5: (¡próximo evento!)

 ¡Próximo Evento!

jover1000x125

Comparto con vosotros que en fechas cercana, el 26 y 27 de Marzo se celebrarán sendos seminarios gratuitos, en Tenerife y Santiago de Compostela respectivamente, organizados por Danysoft, que como sabéis es el partner español.

¡Os animo de verdad a quienes podáis asistir, que no faltéis a esta cita! En este caso, ambos seminarios serán presenciales, lo cual abre una oportunidad magnifica para los compañeros de esas zonas, que habitualmente no lo tienen tan fácil para desplazarse a Madrid y Barcelona, que son las ciudades en las que tradicionalmente se han organizado y celebrado estos seminarios.

¡Visitad el enlace de la imagen para ver el contenido con detalle.

En estos seminarios habitualmente se comentan las ultimas noticias de nuestra herramienta y de su futuro próximo. Es un buen momento para ponerte al día en las novedades. Asimismo, Luis Alfonso Rey, habitual ponente, compartirá con vosotros la creación de servicios REST apoyados en DataSnap para la creación de aplicaciones web HTML5.

Y tras el descanso, se abre una sesión de trabajo centrada en las aplicaciones Android.

¡Creo que ambas prometen ser muy interesantes por lo que no he dudado en abrir esta entrada para compartirlo con vosotros!.

Saludos y que los disfrutéis

AWSyDataSnap

TALLER PRÁCTICO: CURIOSEANDO EN AWS Y DATASNAP (2/2)

Vamos a avanzar en esta ultima parte de la serie, como prometimos, e intentaremos abordar -paso a paso-, con el máximo detalle, la puesta en marcha de este escenario que planteamos, toda vez que nuestra primera entrada nos permitió dar una introducción rápida pero no pudimos ver el detalle de pasos a seguir, que sin duda os ayudará. Esta entrada va dirigida especialmente a los que dais vuestros primeros pasos, como siempre, que sois quien mas ayuda necesitáis. Podéis acceder al enlace a la primera parte de la serie:  Taller práctico: Curioseando en AWS y DataSnap (1/2)

Así que me he armado de paciencia y me he dispuesto a repetir todo el proceso nuevamente, desde la creación de la instancia hasta que el servicio de DataSnap estaba exponiendo datos desde la Nube. Y en cada paso, he hecho una captura, incluyendo al final un video que os muestra básicamente, como se estaba ejecutando el servidor de datansap y enlazaba con el cliente abierto en mi herramienta de desarrollo, tras insertar la ip publica de acceso, vía tcp/ip.

Por supuesto que a estas horas, tras las capturas e iniciar la escritura de estas lineas, los recursos creados, incluyendo instancias EC2, pares de claves y contraseñas, direcciones ip o das, etc, se eliminaron y no puedo repetir ni corregir nada de lo que se pueda haber capturado. El video solo tiene unos minutos pero lo suficiente para que veáis que se produce la conexión entre la capa cliente y el servidor de datasnap.

Respecto a la imagen que compartíamos y que esquematizaba el escenario, me quedaba la idea de que podía resultar un tanto vaga por lo que me vais a permitir que hagamos un par de cambios. Ayudado de la aplicación rediseño el esquema para generar dos ideas muy similares pero un matiz que las hacen distintas.

El primer escenario, un poco mas real que esa primera imagen, situaría nuestra capa de datos en algún lugar de Internet, posiblemente en un servidor compartido, que sería accedido por un servidor de DataSnap ubicado en la Nube. En la parte inferior, he situado lo que representa a una Red, que también es alimentada desde los servicios del Servidor ubicado en su interior. Es mas similar a la situación que planteaba Germán en su serie.

Esta es la imagen:

 

AWSyDataSnap_III

La segunda es similar, pero el matiz es que hemos ubicado nuestra capa de datos en el interior de la Red, que representa a la Empresa que la esta explotando, y que interpone entre los clientes externos y el servidor de BBDD la capa del Servicio de DataSnap en la Nube.

AWSyDataSnap_II

Estos despliegues, nos podrían permitir establecer reglas concretas de acceso al firewall que protege al sistema en el que se ubica la BBDD, toda vez que únicamente nuestros servicios de DataSnap van a estar autorizados a su acceso y puede generarse reglas adecuadas para autorizar o denegar la comunicación. En este esquema, nunca se accedería de forma directa a nuestra BBDD, al menos desde fuera de nuestra RED local. Desde dentro de la RED siempre va a haber alguien que mande mas que nosotros y que pervertirá nuestro sistema.

:-D

Preparativos: algunos pasos a seguir…

Nuestro punto de partida es el acceso a lo que sería el tablero de administración del servicio de EC2, que es la imagen que a continuación podéis ver.

Captura01

Así que vamos a empezar. Parto del supuesto de que os habéis registrado ya en AWS y que habéis iniciado el proceso de activación del servicio de EC2, que os obligará necesariamente a aportar una tarjeta de crédito. Esto os dará acceso a la zona de administración referida (*).

(*) ¡Ya! Imagino lo que pensáis .. A mi tampoco me hace gracia dar una tarjeta de crédito para hacer pruebas, pero si queremos ser parte del sistema y que AWS nos considere usuarios “reales” no nos queda mas remedio que transigir.  Fiel a mi desconfianza en todos sistemas, sobretodo en los que presumen de ser seguros, di mi número de tarjeta cash que tiene un par de eurillos para las emergencias.    :-D    ¡Es broma!

Buscad bajo el título Créate Instance, el botón Launch Instance que iniciará el proceso de creación de la instancia de Amazon EC2, nuestro servidor virtual.

El proceso nos llevará a concretar los datos de que tipo de instancia va a ser creada e los detalles de configuración que podamos necesitar ajustar previamente.  En la parte inferior, podéis ver el despliegue de pasos (el pluggin de WordPress os permitirá recorrerlos pulsando en los botones laterales, leyendo los comentarios ubicados en la parte inferior).

Así que adelante. Vamos a crear la instancia:

Entre los enlaces que tenemos a mano en la documentación, os incluyo este para los que todavía tengáis alguna duda de como hacer una conexión remota desde vuestro sistema, Connecting to Windows Instances Using RDP.

El resultado final es el acceso a la maquina virtual, como se puede apreciar por la siguiente imagen:

Captura_ConnectInstance03

Ahora ya estamos preparados para subir nuestro exe incluyendo el servicio de DataSnap y lanzar su  ejecución para probarlo. Puede bastar un copia pega si vuestro sistema local es windows y el acceso remoto permite compartir el contenido del portapapeles. En caso contrario, cualquier sistema ingenioso puede ser usado (¡no te cortes en esas minucias! :-P ).

Mas sabe el diablo por viejo…

 Lo dice el dicho y casi siempre con razón. El diablo sabe mas por viejo que por diablo y metidos en estas harinas, no deberías subir a tu maquina virtual solo el servidor, sino que para esta primera prueba, harías bien en subirte el cliente de datasnap. Mas que nada porque puedes descubrir que, aunque se ejecute correctamente nuestro servicio, la invocación de los primeros metodos desde el cliente haga que emergen los errores de conexión a la capa de datos.

De hecho, guardé tres capturas de los diferentes errores que fueron emergiendo, pasando a dar solución a cada uno de ellos.

El primer error, provenía de que el sistema carecía de los drivers de conexión propios de la parte cliente motor de Sql Server y la advertencia nos hacía pensar en que era necesaria la búsqueda en internet.

Captura_Errores01

En este caso concreto, el servidor de DataSnap del Taller de Delphi Basico, intentaba conectarse a la base de datos de SQL Server ubicada en el servidor compartido de mi dominio y el problema es que no encontraba el cliente de conexión para SQL Server. Así que procedimos a buscarlo

Microsoft SQL Server 2008 Service Pack 3 Feature Pack

Y seguidamente, lo instalamos en la maquina virtual. Podeis seguir los pasos en la siguiente galería de imágenes:

Si que me gustaría resaltar de las imágenes anteriores, que pongáis atención a elegir correctamente el cliente adecuado a 32 o 64 bit. Si os fijáis, el paquete incluye la descarga de ambos y por tanto, podéis accidentalmente confundirlos.

Y seguidamente otros errores menores…

Tras solucionar el problema anterior quizás descubras que falten algunas librerías que tu sistema local encuentra y que en la maquina virtual no existen. Fue el caso de la librería de dbexpress dbxmss.dll que no se encuentra y que posiblemente no habrás advertido de copiar en un momento inicial.

Captura_Errores02

O bien, en la parte cliente, la librería midas.dll, si no se ha enlazado en el ejecutable. Es posible, dependiendo de la naturaleza de tu servidor y de tu cliente, que aparezcan estas librerías u otras.

Captura_Errores03

Hecho esto, y subsanados todos los errores que fueron emergiendo, fui capaz, ¡por fin! de ver ejecutarse en mi maquina virtual mi cliente de DataSnap consumiendo datos del servicio DataSnap en ejecución. Había ganado parte de una batalla y me sentía feliz.

En la captura podeis ver la ventana de acceso a la aplicación que pudimos compartir en el Taller, ejecutándose en el servidor virtual de forma local.

Captura_Exito

Ganar la batalla y ganar la Guerra.

Estamos ya acabando. ¡No os desespereis!.

Nos quedan dos cosas importantes que no debéis de olvidar

1º Tenemos que revisar el Firewall de Windows de nuestra maquina virtual, para que nuestra aplicación pueda exponer hacia el exterior el puerto de comunicación, y que pueda ser encontrado por el sistema interesado. En nuestro caso, en las reglas avanzadas del Firewall de Windows Server 2012 dimos de alta el puerto 211  en la zona de comunicaciones entrantes.

A partir de ese momento, en teoría deberíamos ser capaces de ver nuestro servicio de datasnap en la red.

De forma similar, nuestra consola de Gestión en la Maquina Virtual, permite crear reglas de acceso y salida, permitiéndonos dotar de mayor seguridad a nuestro despliegue o proyecto.

Esta es una captura de la zona que administra la política de acceso que gestiona la consola de administración de EC2.

CapturaGruposSeguridad

 

En este punto, no deberíamos dejar abiertos, definidos como 0.0.0.0, los accesos RDP.

 

2º Ahora podemos también establecer determinadas políticas de acceso y seguridad a nivel de firewall y reglas, en lo que atañe a la capa de datos, que puede en alguna medida evitar comprometerse, ya que solo deberíamos permitir el acceso a la capa de datos mas que de los servidores que autoricemos a conectar.

El video finalmente, nos muestra como conecto mi cliente local, desde el entorno de desarrollo, para que apunte al nuevo servidor en la nube, modificando el path de conexión del componente que representa el driver de conexión de datasnap, con la nueva ip.

Espero y deseo que os haya gustado y os pueda ayudar.

Sed felices y buen camino.

 

AWSyDataSnap

Taller práctico: Curioseando en AWS y DataSnap (1/2)

Mis saludos en este principio de semana lluvioso y tristón, acompañado de esa llovizna ligera y unas nubes bastante grises y plomizas. ¿Que tal, compañeros?

Cualquier fecha es buena para retomar la actividad.   :-)

Así pues, me reencuentro con vosotros con esta entrada que abre el año 2014, tras un periodo de algunos meses en los que ha predominado ciertamente la ausencia, aunque para ser justos, producida ésta por motivos de trabajo. Quiero decir con eso que para mi sigue siendo importante este blog y lo que pueda aportar a la Comunidad, desde la humildad con la que intento que siga adelante. 

Pero es verdad que lo que mas se ha resentido en estos dos o tres últimos meses, ha sido el blog, ya que, el poco tiempo libre, en la medida que me ha sido posible, lo he dedicado a seguir el contacto de la Comunidad a través de la actividad desplegada en el grupo de Facebook, que conocemos como Delphi Solidario, y que gracias a la implicación de todos sigue siendo día a día un motor de noticias y un indicativo del pulso de una parte de nuestra Comunidad. En el otro lado seguimos teniendo los pilares que suponen los dos grandes grupos que en buena medida la representan, Club Delphi y Delphi Access, y que acogen a un buen porcentaje de compañeros que activamente siguen apoyando y compartiendo su tiempo, bien a través de las publicaciones en blogs, bien a través de los foros y comentarios públicos en las entradas. Si os estáis acercando por primera vez a Delphi a través de esta entrada, (a veces se dan esas casualidades), no dejéis de visitar y explorar todos los recursos que encierran estas dos grandes comunidades de amigos, y sin duda de grandes profesionales.

Pero vamos a lo que vamos… al grano…

A mediados de Enero, justo antes de que publicara mi buen amigo German Estévez, del blog /*Prog*/Delphi-Neftalí/*finProg*/, la primera de las entradas de la serie: (1/5) Aplicación de acceso a datos (Introducción), compartía con él varios correos sobre lo que realmente es el meollo de la serie que luego ha ido publicando. Vaya por delante mis felicitaciones a Germán por la gran calidad de sus artículos, que injustamente. estamos tan acostumbrados, que no los valoramos suficientemente, por cuanto suponen esa programación mas cercana a nuestra realidad y vivencias y siempre útil, algo que sin duda se agradece. Así que mi recomendación, a quienes se acercan a este blog, que no dejen de visitar sus aportaciones en esa y otras series anteriores. ¡Felicidades Germán!.

La discusión era fácil de resumir desde mi punto de vista: desgraciadamente existen contextos donde no siempre podemos fácilmente desplegar el numeroso abanico de altas y grandes capacidades que nos da la herramienta y nos enfrentamos a tomar decisiones en base a estas limitaciones que realmente no atañen a la herramienta en si, sino al contexto real que vivimos. Ese es un poco el quid de la cuestión.

Podéis leer el ejemplo que pone Germán en esa primera entrada introductoria, donde establece un hipotético proyecto en base a unas condiciones previas que nos limitan,  creo yo, como un arquetipo de esa inquietud que puede manifestarse de mil formas. En las empresas que conozco, empresas pequeñas o medianas, con pocos recursos en algunos casos, es relativamente sencillo montar  un esquema cliente-servidor o incluso un despliegue de múltiples capas apoyado en DataSnap, dentro del área de red de la empresa, por supuesto, ¡considerando este caso como un caso reducido y aislado en ese Universo!. Fuera del caso singular, las cosas adquieren muchas ópticas y las decisiones no son hechas de forma sistemática sino que requieren de nuestra habilidad para sacar el máximo partido y explotar al máximo los recursos que disponemos.

Tenemos una herramienta de propósito general ciertamente con puntos fuertes en cuanto a drivers de conexión a datos, que se combinan con múltiples tecnologías y ahora inclusive en distintas plataformas , lo cual nos da un abanico muy grande de posibilidades.  Y el hecho de que los sistemas windows estén tan extendidos frente a otros sistemas es otro plus a favor en ese contexto que nos favorece (al menos en lo que atañe a los servidores datasnap)

Si tuviera que resumirlo en una sola palabra, casi seguro que elegiría la palabra “limones”, algo muy valenciano, de mi tierra…

 limones

Ese dicho de que la vida nos da limones, no Naranjas como muchos quisiéramos de antemano, y aprendemos a sacar el jugo para regalarnos una limonada muy fresca o como dicen algunos, para combinar la sal y el tequila.

:-)

En la serie que Germán está compartiendo con nosotros, la solución de urgencia es ese WebService en php que aprovecha así la posibilidad de exponer desde un servidor linux compartido, algo que es fácilmente accesible y disponible por las Empresas. Luego, el consumo de los datos desde la parte cliente, aprovecha toda la potencia que nos da Delphi: iOS, Android, MacOSX, Windows de Escritorio, etc… 

Esquema

Imagen de la Serie en el Blog Delphi-Neftali

Pues bien… Nuestra discusión giraba en torno a todo esto, filosofando en una tarde cualquiera, pero quizás mi curiosidad me llevaba a buscar otras posibilidades, que no había probado…

Y si mi servidor de datasnap…

Esta era la pregunta que en ese momento me hacia ¿Y si mi servidor de DataSnap estuviera en la Nube?.  Fue precisamente una de las preguntas que cruzamos y que yo me había hecho tiempo atrás, y que en ese momento, sinceramente, no tenía respuesta porque no había dedicado tiempo a experimentar. Tampoco sabia si existía algún tipo de impedimento técnico, fuera de que sea mas o menos oneroso o mas o menos inseguro. Así que mi despedida se cerraba con el comentario a German en el sentido de que intentaría complementar su serie con esta posible experiencia. Y bueno… realmente eso ha sido lo que ha motivado estás lineas.

 Me hice un esquema gráfico que visualizara la idea que quería experimentar

AWSyDataSnap

Bueno… ¡visto así parecía algo factible!. Un servicio de base de datos alojado en cualquier servidor compartido de Internet, exponiendo públicamente una instancia de mysql o similares para linux. También podría ser un servidor compartido windows, con Sql Server, (que concretamente es el caso del servidor que aloja el sitio de este blog y que nos valió en su día para probar el ejemplo del Taller de Delphi Básico). O incluso, llegado el caso nuestro propio servidor en la plataforma adecuada, desde alguna ip fija, en la empresa o cualquier otro lugar de confianza con la base de datos elegida. Y por otro lado, una instancia de servidor virtualizado en la nube, como la solución que nos ofrece Amazon Web Services (AWS), desde el servicio de EC2, exponiendo nuestro servicio de DataSnap. Y en la parte exterior, consumiendo los datos, los clientes nativos de las distintas plataformas que son posibles generar desde nuestra herramienta. Con total independencia de que esos datos expuestos desde la nube fueran entregados desde un webservice o una canalización TCP/iP.

Si nos vamos a lo concreto, para este experimento, la receta mas o menos siguió estos pasos:

1- Abrir una cuenta en AWS y tras ese registro inicial cumplimentar todos los requisitos. Esta cuenta nos da acceso a un abanico amplio de servicios en la nube, entre los que se encuentra el que hace referencia a la virtualización de servidores.

2- Activar una licencia de Windows Server 2012 en el servicio de EC2 (Amazon Elastic Compute Cloud o Amazon EC2).

3- Subir a ese servidor en ejecución, el servidor de DataSnap que usamos en el Taller de Delphi Básico celebrado en la semana del 26 de Octubre de 2012, compilado ahora con Delphi XE5, y

¡voila! El cliente de DataSnap, ejecutado desde mi equipo, encontraba el servicio que exponía el servidor de DataSnap desde la nube, accediendo a los datos de un servidor compartido  windows (el de mi blog) que alojaba una instancia de SQL Server, justo lo que se mostraba en el esquema que compartía al inicio.

El que ese servidor de bbdd estuviera fuera de esa Nube, como era el caso, o que se incluyera dentro de ese u otro servidor en Amazon EC2, que podía incluir el motor de SQL Server, era un poco lo de menos. Como reza el apartado que explica el servicio, el peso fuerte de  AWS es la posibilidad de dotar a nuestros proyectos de recursos escalables y personalizados a la medida de nuestras necesidades.

Esta es, por ejemplo una vista de los servicios que se pueden contratar desde nuestro perfil en AWS:

servicios_aws

 

El servicio de EC2: Unas pinceladas

La idea que uno puede tener de sus servicios antes de conocerlos puede ser un tanto vaga ya que si os fijáis en la imagen superior, AWS recoge tanto las áreas de computación y redes, almacenamiento de datos, analítica, desarrollo y aplicaciones de servicio. He contado a bote pronto unos 27 servicios distintos, gestionados a través de un interfaz web y una consola de gestión de servicios que nos permitirán administrarlos de una forma relativamente sencilla, sobretodo si tenemos en cuenta la complejidad que encierran.

La documentación es amplia. En muchos caso está traducida a nuestro idioma. Adentrarnos en este mundo puede suponer la lectura de muchas paginas para tener una buena idea, a pesar de que el contacto con la Nube se facilita en buena medida. De hecho, en mi opinión resulta impagable la capa gratuita que dispone AWS para que el usuario se inicie y pueda poner en marcha sus pruebas de desarrollo con el menor coste posible (coste cero si la usamos de forma adecuada). Al registrarse, los nuevos clientes de AWS reciben cada mes y durante un año los siguientes servicios de EC2:

      • 750 horas de uso para la ejecución de instancias Linux/Unix Micro en EC2
      • 750 horas de uso para la ejecución de microinstancias Microsoft Windows Server en EC2
      • 750 horas de Elastic Load Balancing más 15 GB de procesamiento de datos
      • 30 GB de almacenamiento del volumen estándar de Amazon EBS más 2 millones de E/S y 1 GB de almacenamiento de instantáneas
      • 15 GB de ancho de banda saliente en todos los servicios de AWS
      • 1 GB de transferencia de datos regional
(datos extraídos de https://aws.amazon.com/es/ec2/pricing/

EC2 básicamente nos ofrece la posibilidad de virtualizar servidores en la Nube. Toma ventaja desde el momento en el que disponemos de un control absoluto de las instancias creadas y se integra dentro de un esquema de pago por uso, con un catalogo amplio de opciones, inclusive contamos con la posibilidad de adquirir instancias de software preconfiguradas y listas para su uso desde la tienda de Amazon (AWS Marketplace): https://aws.amazon.com/marketplace

Creo que no está de mas conocer las posibilidades que nos pueden aportar, por lo que os invito a que  leáis esta documentación que os introduce en el servicio y sus posibilidades:

https://aws.amazon.com/es/ec2/

Por supuesto otro punto fuerte es la escalabilidad, que sea adaptable a nuestras necesidades pudiendo ajustar y personalizarlo con el software que necesitemos.

Opciones de instancias de Amazon EC2 en la capa gratuita

Para que veáis que el abanico disponible es amplio, he generado una pequeña tabla que resume y extrae los datos de los sistemas operativos disponibles en la capa gratuita. Con todos ellos vamos a poder hacer pruebas, casi todos disponibles tanto en 32 bits como en 64. 

    FREE TIER
_amazon_linux  Amazon Linux  32 64
 The Amazon Linux AMI is an EBS-backed, PV-GRUB image. It includes Linux 3.4, AWS tools, and repository access to multiple versions of MySQL, PostgreSQL, Python, Ruby, and Tomcat.
 _red_hat  Red Hat  32  64
    Red Hat Enterprise Linux version 6.4, EBS-boot.
 _suse_linux  SUSE Linux  32  64
   SUSE Linux Enterprise Server 11 Service Pack 3 basic install, EBS boot with Amazon EC2 AMI Tools preinstalled; Apache 2.2, MySQL 5.5, PHP 5.3, and Ruby 1.8.7 available
 _ubuntu Ubuntu  32  64
Ubuntu Server 12.04.3 LTS with support available from Canonical
_ubuntu Ubuntu 32 64
Ubuntu Server 13.10, with support available from Canonical (http://www.ubuntu.com/cloud/services).
_windows  Windows  64
 Microsoft Windows 2012 Standard edition with 64-bit architecture.
 _windows   Windows  64
 Microsoft Windows 2008 R2 SP1 Datacenter edition and 64-bit architecture. [Multi-Lang]
 _windows   Windows  32  64
 Microsoft Windows 2008 R1 SP2 Datacenter edition. [English]
(datos extraídos de https://aws.amazon.com/es/ec2/purchasing-options/)

A modo de conclusión

Esta entrada nos sirve como introducción, presentando el experimento o idea, y en la segunda parte, que preveo la pueda tener preparada al fin de esta misma semana, comentaríamos con un pequeño vídeo o imágenes los pasos y algunos problemas que solucioné sobre la marcha, de forma que vosotros mismos podáis hacer alguna prueba.

Disponer de un servidor virtualizado en la Nube puede tener algunas ventajas frente a la opción de exponer públicamente el servicio de DataSnap desde un servidor propio, con salida a través de algún router y adsl al uso.  Por un lado me parece evidente que se interpone el acceso a la dirección real de ubicación de nuestro servicio de bbdd, algo que parece recomendable desde el sentido común y desde el punto de vista de la seguridad, puesto que podemos establecer reglas de confianza en la comunicación de la capa de datos y la capa del servicio. Por otro lado, el servicio es escalable y personalizable. Podríamos tener múltiples servidores llegado el caso y  crear estrategias de balanceo de carga en función de los picos que el propio negocio genera. Son muchos detalles que hacen interesante explorar las ventajas de la Nube, que lógicamente no voy a descubriros yo.

Y para finalizar, a algunos quizás les de una alegría al comentar que me propongo volver a realizar en fechas cercanas nuevamente el Taller que hicimos sobre DataSnap, al que hacia referencia a lo largo de la entrada. Un taller gratuito y con un numero pequeño de plazas y que sigue en esa linea de ayudar a quienes dan sus primeros pasos. No anticipo nada mas   :-D

Buen camino a todos.

jover160x600

Una anécdota sobre TScrollBox y última promoción de Rad Studio XE5

Cuando empecé a escribir esta entrada, hace ya varios días, mi pensamiento era básicamente resaltar la última promoción de Embarcadero, que a priori y solo por el valor añadido que aporta, creo que se puede valorar como muy interesante. De hecho, si fuera el caso que estuvierais en estos momentos valorando la adquisición del producto, supone la oferta de fin de año un bonus importante en descuentos y herramientas adicionales que siempre se agradecen en los tiempos actuales de crisis. Por otro lado, el partner de Embarcadero para vuestra área, casi con seguridad va a ofreceros  valor   añadido que se va a poder agregar a dicha compra (sé por lo leído en correos que por ejemplo Danysoft tiene preparada también ofertas que cierran el año y las señalaremos al final de esta entrada).

Decía que estaba metido de lleno en el tema de la preparación de la entrada, familiarmente lo referimos como metidos en harina :-D. Había añadido tanto la imagen que luce en la oferta de Embarcadero como el contador de tiempo atrás. El contador, bajo la imagen, debería indicar el tiempo que falta hasta el 31 de Diciembre de 2013, fecha en la que finaliza la oferta de Embarcadero. También tenía preparado parte del texto para buscar la traducción mas adecuada o cercana, y no recién había añadido esto último, la recepción de un correo de un compañero cambiaba o daba un giro a las expectativas de la propia entrada…

¡ULTIMA OFERTA DE EMBARCADERO!

ofertaxe5dic2013

Así que la oferta de Embarcadero tenía que esperar. Dejé el texto del detalle en la parte inferior de la entrada y abrí un hueco para incluir la anécdota de mi amigo.

 El punto de partida de Seguismundo…

El correo de este compañero y amigo, al que podemos llamar Seguismundo, (por aquello de que tenga un nombre), formaba parte de otros muchos correos que desde tiempo atrás he ido recibiendo, quizás porque la comunidad es cada vez mas grande y las relaciones entre los que la componen se van estrechando. No es rara la semana que no se reciba algún correo fruto de las entradas del blog o de la actividad del grupo de Facebook.

En este caso, Seguismundo andaba con la idea de crear un componente contenedor muy sencillo, que le permitiera definir filas y columnas sin ceñirse a los tradicionales que todos conocemos. Buscaba algo mas casero para experimentar.

Me planteaba así su problema de esta forma:

 [...] 
Quiero hacer un componente en FMX que se asemeje a una grilla, es decir un título, un encabezado de columnas y las respectivas filas de datos para cada columna, todo iba muy bien hasta que llegué al punto de poner las filas (es decir una serie de columnas dentro de un TLayout) que llegan a un componente TVertScrollBox (o ScrollBox pasa lo mismo) y allí, no encuentro la manera de que las columnas se pongan en el orden correcto. 
[...]

y proseguía pidiéndome que compilara el código con XE5 por aquello de que pudiera ser un bug ya solucionado. Adjunto a su correo, Seguismundo incluía el conjunto de ficheros de una aplicación de pruebas, para poder mostrarme el problema, lo cual me alegró sobremanera ya que resulta en ocasiones complicado tras la lectura de un correo averiguar que problema realmente se padece.   8-O

Me puse pues a analizar qué había recibido y observé con detenimiento las unidades que Seguismundo me había enviado, concretamente la unidad UPruebaGridFM.pas, que era la que contenía los objetos de la interfaz y la unidad UClassGrillaTest, que era donde había declarado una clase que representaba cada fila del contenedor, responsable de crear 5 etiquetas a piñón.

Lo siguiente fue abrir el entorno de XE5 y compilar el paquete recibido. No se había generado ningún error… ¡vamos bien! pensaba para mi. Y ¡voila! allí se estaba ejecutando el ejemplo de Seguismundo.

El interfaz no podia dar lugar a errores de interpretación. Tres botones que al pulsarlos, rellenaban sucesivamente filas de etiquetas agrupadas en un contenedor que representaba conceptualmente una fila, dentro una instancia de TLayout, otra de TRectangle y finalmente en una instancia de TScrollBox respectivamente.

 

PuntoPartidaTest

Respecto al problema que él me comentaba no veia nada raro… A ojo de buen cubero no acababa de ver cual era realmente el problema (al menos respecto a la ordenación de las etiquetas creadas), por lo que decidí enviar de vuelta una respuesta rápida a Seguismundo, para comentarle que no sabía exactamente a que se refería. Evidentemente sí habían otros puntos que no me parecían correctos formalmente y en ese mismo correo ya lo compartía con él.

Código de la Unidad UPruebaGridFMX de Seguismundo

unit UPruebaGridFMX;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
  FMX.StdCtrls, FMX.Layouts, UClassGrillaTest, FMX.Objects;

type
  TForm10 = class(TForm)
    ScrollBox1: TScrollBox;
    btnTestLayout: TButton;
    btnTestRectangle: TButton;
    Layout1: TLayout;
    Rectangle1: TRectangle;
    btnTestScrollBox: TButton;
    procedure btnTestLayoutClick(Sender: TObject);
    procedure btnTestRectangleClick(Sender: TObject);
    procedure btnTestScrollBoxClick(Sender: TObject);
  private
    { Private declarations }
    Grilla: TComp1;

    procedure NuevoObjeto;
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.fmx}

procedure TForm10.btnTestLayoutClick(Sender: TObject);
begin
  Grilla := TComp1.Create(nil);
  Grilla.FLayout1.Parent := Layout1;
  NuevoObjeto;
end;

procedure TForm10.btnTestRectangleClick(Sender: TObject);
begin
  Grilla := TComp1.Create(nil);
  Grilla.FLayout1.Parent := Rectangle1;
  NuevoObjeto;
end;

procedure TForm10.btnTestScrollBoxClick(Sender: TObject);
begin
  Grilla := TComp1.Create(nil);
  Grilla.FLayout1.Parent := ScrollBox1;
  NuevoObjeto;
end;

procedure TForm10.NuevoObjeto;
begin
  with Grilla do
  begin
    FLayout1.Align := TAlignLayout.alBottom;

    FLabel1.Align := TAlignLayout.alRight;
    FLabel1.AutoSize := False;
    FLabel1.Text := IntToStr(X) + '1';
    FLabel1.Width := 50;
    FLabel1.Align := TAlignLayout.alMostLeft;

    FLabel2.Align := TAlignLayout.alRight;
    FLabel2.AutoSize := False;
    FLabel2.Text := IntToStr(X) + '2';
    FLabel2.Width := 50;
    FLabel2.Align := TAlignLayout.alMostLeft;

    FLabel3.Align := TAlignLayout.alRight;
    FLabel3.AutoSize := False;
    FLabel3.Text := IntToStr(X) + '3';
    FLabel3.Width := 50;
    FLabel3.Align := TAlignLayout.alMostLeft;

    FLabel4.Align := TAlignLayout.alRight;
    FLabel4.AutoSize := False;
    FLabel4.Text := IntToStr(X) + '4';
    FLabel4.Width := 50;
    FLabel4.Align := TAlignLayout.alMostLeft;

    FLabel5.Align := TAlignLayout.alRight;
    FLabel5.AutoSize := False;
    FLabel5.Text := IntToStr(X) + '5';
    FLabel5.Width := 50;
    FLabel5.Align := TAlignLayout.alMostLeft;

    FLayout1.Align := TAlignLayout.alMostTop;
  end;
end;

end.

 

 

Código de la Unidad UClassGrillaTest de Seguismundo

unit UClassGrillaTest;

interface

uses System.Classes, FMX.Layouts, FMX.StdCtrls, FMX.Types, FMX.Objects;

type
  TComp1 = class
  public
    FLayout1: TLayout;
    FLabel1: TLabel;
    FLabel2: TLabel;
    FLabel3: TLabel;
    FLabel4: TLabel;
    FLabel5: TLabel;

    class var X: integer;

    constructor Create(AReceptor: TFmxObject);
  end;

implementation

{ TComp1 }

constructor TComp1.Create(AReceptor: TFmxObject);
begin
  FLayout1 := TLayout.Create(nil);
  FLayout1.Parent := AReceptor;

  FLabel1 := TLabel.Create(nil);
  FLabel1.Parent := FLayout1;

  FLabel2 := TLabel.Create(nil);
  FLabel2.Parent := FLayout1;

  FLabel3 := TLabel.Create(nil);
  FLabel3.Parent := FLayout1;

  FLabel4 := TLabel.Create(nil);
  FLabel4.Parent := FLayout1;

  FLabel5 := TLabel.Create(nil);
  FLabel5.Parent := FLayout1;

  Inc(X);
end;

end.

 

Su correo no se hizo esperar y de vuelta su respuesta me indicaba el problema…

Hola Salvador, gracias.  El problema se ve en la primer fila del ScrollBox, que para el ejemplo que capturaste es: 31 35 34 33 32, como puedes ver las demás si se ordenan correctamente p.ej. 81 82 83 84 85.
Lo anterior significa que aún en XE5 sucede igual, lo que no sé es si eso se debe a alguna parametrización en el ScrollBox o a un manejo en especial …?
Seguismundo
 

 En fin… Volví a observar con detenimiento la captura recibida y asentía dandole la razón. En la imagen inferior se puede ver que en la instancia del TScrollBox, la primera fila de etiquetas se ordenan de una forma extraña y únicamente sucede en dicha fila. En los otros componentes similares el código funcionaba de una forma similar a como el autor, Seguismundo, esperaba: {31,35,34,33,32.. 81,82,83,84,85…}. Ok -pensé para mi-

 

Detalle

 Por qué las cosas pasan porque pasan…

Sobre este supuesto le envié un correo de cortesía a Seguismundo, para comentarle que iba un poco liado y que tan pronto como me fuera posible le comentaba algo. Y me puse a ver ese código con mas detenimiento, cosa que me ocupo un par de días mas.

Las cosas siempre pasan por alguna razón. En nuestra profesión no hay magia aunque a veces los usuarios con los que convivimos nos concedan poderes mágicos. :-D  No es raro que cuando me llaman tanto Yolanda como Trini, de Administración, porque pongamos por caso no les funcione la impresora, la simple presencia de un servidor haga que el chisme imprima correctamente, y que estas santas mujeres acaben pensando que soy capaz de alterar mágicamente un solo byte. También mis amigos en ocasiones descubren que puedo apagando y encendiendo un router solucionar un problema de la adsl. Nos llegamos a convertir en una especie de talismán.

:lol:

Pero en nuestro mundo, el de las personas que resolvemos problemas a través de estos lenguajes mágicos que hacen cosas triviales, descubrimos por experiencia que todo pasa por una razón también, aunque en ese momento no seamos capaces de verla.

El código de Seguismundo tenía algunos problemillas fuera de lo que era el propio error detectado, visible a simple vista.

Si os parece podemos comentarlas.

Por ejemplo. Seguismundo declaraba la clase TComp como descendiente de TObject, en su tipo

type
  TComp1 = class
  public
...

por lo que las instancias creadas no entraban en el flujo de destrucción automática relativas al propietario (el owner) y en un ambiente de escritorio deberían ser expresamente liberadas. El parámetro del constructor lo utilizaba para asignar una referencia válida al parent de los componentes que internamente manejaba TComp.

constructor TComp1.Create(AReceptor: TFmxObject);
begin
  FLayout1 := TLayout.Create(nil);
  FLayout1.Parent := AReceptor;
...

y quedaban finalmente, tanto los TLabel como los TLayout, emparentados pero huérfanos de padre, lo cual es una situación un tanto extraña. Es mas, podían llegar a existir potenciales problemas de memoria, instancias que fueron creadas y que quedaron en el limbo de aquellas referencias que no podrían ser alcanzadas jamas… Esa situación sucedía cuando repetías el click del botón sucesivamente, ya que FLabel1 y resto de presuntos implicados, siempre iban a apuntar a la ultima instancia creada, dejando en el olvido las anteriores.

Por otro lado, cada instancia de TComp, sufría un problema similar.

Grilla := TComp1.Create(nil);

Cierto que era código para andar por casa, y así lo entendía yo al recibirlo, pero en mis correos de vuelta, todos estos comentarios estaban entre las cosas que compartimos.

De hecho, aun suponiendo que estuviéramos en el ámbito de las aplicaciones móviles, en donde el sistema de ARC, automatiza la destrucción de las instancias en función de un contador interno, el código tampoco hubiera funcionado correctamente y establecía efectos indeseados que a simple vista no eran tan aparentes.

Por ejemplo, supongamos que llevamos el código a las plataformas móviles:

La ejecución del código que asignaba la referencia a la fila del contenedor

  Grilla := TComp1.Create(nil);
  Grilla.FLayout1.Parent := ScrollBox1;

provocaría en ese caso, que al salir de ámbito, a partir de la segunda vez que el botón fuera pulsado, fuera destruida la instancia de TComp creada en la pulsación anterior, puesto que el contador de referencias se decrementa y al llegar a cero, la instancia pasa a mejor vida. El resultado final, no aparente, habría dejado todas las etiquetas esparcidas en el contenedor desligadas de su contenedor fila (TComp en el ejemplo) salvo las de la ultima instancia creada, aspecto este que no era el inicialmente planeado por el autor del código supongo. Eso se puede ver fácilmente estableciendo un punto de parada en una linea de su destructor, si fuera añadido.

Si alguno de vosotros tiene duda os aconsejo dar un vistazo a algunos enlaces de Marco Cantú

http://blog.marcocantu.com/blog/delphi_arc_android.html y

http://edn.embarcadero.com/article/43073,  principalmente este último.

Pero si fuéramos a analizar con mas detalle la ejecución del código que me envió Seguismundo, en el caso concreto de que pulsáramos sobre el botón asociado al contenedor de ScrollBox repetidamente, observaríamos dos efectos anómalos:

1- El scrollbox nunca nos mostraria la barra de scroll horizontal (aun en el caso de existir condiciones de que fueran visibles)

2- Cuando la cantidad de filas desbordaran la altura de nuestro componente contenedor, descubriríamos que no visualizamos la ultima de ellas, que siempre sería inaccesible.

Todo eso, sin contar el problema inicial detectado, que provocaba que se ordenara de forma incorrecta la primera file de las etiquetas creadas.

Una estrategia equivocada…

Quizás fuera esta la razón, con mas peso, que finalmente motivó el incluir esta anécdota dentro de la entrada. Su razonamiento respecto al uso de la propiedad Align para reubicar los componentes dentro del contenedor de la clase TScrollBox, no funcionaba correctamente pero tenía una cierta lógica que en mi opinión le podía llevar a engaño. Y quizás por eso el compartir estas lineas para que Seguismundo pudiera ver ese matiz

Su razonamiento era mas o menos este:

Quiero colocar cada fila que vaya creando e insertando dentro del contenedor, una pegada a la otra, y que la ultima siempre se acople al final de las que ya existan. 

De igual forma razonaría según esa idea respecto a cualquier alineamiento, fuera hacia arriba, hacia abajo o hacia cualquiera de los laterales.

Puestos en esa tesitura, la propiedad Align es una tentación porque llegas a conseguir eso mismo de una forma sencilla… (la cual no siempre es correcta).

Intentaré demostrarlo.

Supongamos un formulario sencillo que contiene una instancia de TScrollBox de 400×400. Supongamos también que vamos a instanciar de forma repetida unos contenedores vacíos que representarían las sucesivas filas (mas que nada por simplificar) que tendrán unas medidas de 50×600, los cuales queremos colocar uno pegado a otro, de arriba a abajo.

Bajo esos supuestos, la creación del primer contenedor, forzaría a que nuestro padre, la instancia de TScrollBox hiciera visible el scroll horizontal. De igual forma, la repetición sucesiva a partir del quinto layout, forzaría a que fuera visible el scroll vertical, puesto que a partir de la quinta fila el height o altura total de la suma de todas las filas creadas sería mayor que el espacio hábil del contenedor, lo cual debería generar igualmente el conjunto de procesos que permitirá visualizar y manipular las barras de scroll.  

 Si revisamos las unidades del código fuente donde se declara la clase TScrollBox en Firemonkey, FMX.Layouts, veremos que las llamadas que fuerzan a recalcular el contenido del contenedor padre, se centran en la función RealingContent( ), que siempre que es invocada hace dos cosas básicas:

  1. Inicializar los cálculos, invocando a  InvalidateContentSize( ), que hace un reset o puesta a cero de la estructura que representa el área total contenida.
  2. Lanzar el proceso de calculo que produce que se ubiquen correctamente los distintos componentes (en nuestro ejemplo filas) y puedan ser explorados por las barras de scroll. La función Realign( ) es la responsable de todo ello.

Esto sucede durante la vida de nuestra instancia de la clase TScrollBox cuando cambian las medidas de altura o anchura. En esos momentos el componente necesita saber si para el nuevo tamaño qué debe o no debe mostrar. Frente a lo que yo esperaba, mientras estudiaba con puntos de parada el flujo del código, no sucede así cuando cambian el Top o el Bottom del componente. En su lugar, va a considerar los cambios en la propiedad Position que los representan, con los valores X e Y. Por todo ello, y sabiendo que también la asignación del Parent por lógica, lanzará o invocará las rutinas que comentábamos, debería ser está asignación la que hiciéramos en ultimo lugar.

Para verlo, los puntos de parada nos permiten descubrir el verdadero responsable de que todo funcione correctamente. Realign( ) invocará a DoRealign( ) y ésta a InternalAlign( ) que centralizará de alguna forma todo el conjunto de cálculos.

Dentro de esta función encontraremos una invocación a DoCalcContentBounds( ) cuyo valor de retorno va a ser el área total del conjunto de hijos contenidos en el contenedor. Esta es la función:

function TScrollBox.DoCalcContentBounds: TRectF;
var
  i: Integer;
  R, LocalR: TRectF;
begin
  Result := TRectF.Create(0, 0, 0, 0);
  if Assigned(FContent) and Assigned(ContentLayout) then
  begin
    R := ContentLayout.LocalRect;
    for i := 0 to FContent.ControlsCount - 1 do
    if FContent.Controls[i].Visible then
    begin
      {$IFDEF MSWINDOWS}
      if (csDesigning in ComponentState)
        and Supports(FContent.Controls[i], IDesignerControl) then Continue;
      {$ENDIF}
      LocalR := FContent.Controls[i].ParentedRect;
      if (FContent.Controls[i].Align in [TAlignLayout.alTop, TAlignLayout.alMostTop, TAlignLayout.alBottom, TAlignLayout.alMostBottom]) or
         (TAnchorKind.akRight in FContent.Controls[i].Anchors) then
        LocalR.Right := R.Right;
      if (FContent.Controls[i].Align in [TAlignLayout.alLeft, TAlignLayout.alMostLeft, TAlignLayout.alRight, TAlignLayout.alMostRight]) or
         (TAnchorKind.akBottom in FContent.Controls[i].Anchors) then
        LocalR.Bottom := R.Bottom;

      Result.Union(LocalR);
    end;
  end;
end;

Observándola con un poco de detenimiento se puede deducir lo siguiente:

  • Solo va a ejecutarse si el contenedor ha sido asignado. El contenido del contenedor padre es representado por la referencia a ContentLayout. Por esa razón comentaba la conveniencia de asignar la referencia al Parent en ultimo lugar, ya que todos los cálculos van a realizarse tan solo en el caso de que exista esta asignación al Parent. Evitaremos bucles y procesos innecesarios si existen llamadas previas a campos que puedan lanzar el recalculo.
  • Se obtiene un area que representa la posición y tamaño de dicho contenedor padre, que sirve como referencia inicial. Recordemos que se había inicializado previamente.
  • Se recorrerán la matriz que contiene los controles hijos para analizar de que forma afectan al tamaño de ContentLayout siguiendo unas pautas:
    • Si el componente hijo presenta un Align alTop o alBotton, dado que esta acoplado al padre, considerara su valor Rigth (el punto derecho).
    • Si el componente hijo presenta un Align alLeft o alRight, dado que también está acoplado al padre pero por un lateral, considerará pertinente el valor del padre en la parte inferior.
    • Otro valor de Allign va a considerar el área y posición del hijo contenido.
  • De cada transición de ese bucle que recorre los hijos visibles del contenedor va acumulando en el resultado el calculo de la unión de áreas, comparando el área del hijo actual en el bucle con el área previa.

Y nos falta, para darle un vistazo a como se genera esa área resultante, que las tenéis en las tres funciones que siguen a continuación.

class function TRectF.Union(const R1, R2: TRectF): TRectF;
begin
  UnionRectF(Result, R1, R2);
end;

procedure TRectF.Union(const R: TRectF);
begin
  Self := TRectF.Union(Self, R);
end;

class function TRectF.Union(const Points: Array of TPointF): TRectF;
var
  I: Integer;
  TLCorner, BRCorner: TPointF;
begin
  if Length(Points) > 0 then
  begin
    TLCorner := Points[Low(Points)];
    BRCorner := Points[Low(Points)];

    if Length(Points) > 1 then
    begin 
      for I := Low(Points) + 1 to High(Points) do
      begin
        if Points[I].X < TLCorner.X then TLCorner.X := Points[I].X;         
if Points[I].X > BRCorner.X then BRCorner.X := Points[I].X;
        if Points[I].Y < TLCorner.Y then TLCorner.Y := Points[I].Y;         
if Points[I].Y > BRCorner.Y then BRCorner.Y := Points[I].Y;
      end;
    end;

    Result := TRectF.Create(TLCorner, BRCorner);
  end
  else begin
    Result := TRectF.Empty;
  end;
end;

En este punto, podríamos entender el porque de los problemas iniciales.

Si en la hipótesis que lanzamos lineas mas arriba, con un contenedor de 400×400, creáramos nuestro primer Layout hijo de 50×600, y lo acoplaramos con un alineamiento alTop, esa primera llamada funcionaria en cualquier caso correctamente. Basicamente ha sucedido:

  • Creamos el layout.
  • Asignamos el parent.
  • Forzamos Align alBottom para que se sitúe el ultimo.
  • Forzamos Align alTop para que se sitúe en la parte superior.

Cuando se asigna el valor del Parent, el Align del hijo creado es el valor por defecto, alNone, y para ese valor, considerara el área del hijo (50×600), la cual, unida al área del contenido del padre que fue inicialmente respetada dará una área de 50×600.

Para el segundo de los hijos, el área que representa ContentLayout es 50×600. La ejecución resultante de este segundo bloque tras la asignación del Parent sigue siendo 50×600, porque el primer hijo cambió su Align a alTop mientras que el segundo vuelve a tomar el valor por defecto, por lo que accidentalmente nos vuelve a calcular un área de 50×600, lo cual era “erróneo” pero no nos dimos cuenta porque no ha necesitado hacer visibles la barra de scroll vertical, dado que la suma del Height de los hijos no supera la altura del contenedor.

Solo cuando se produzca esta situación, cuando es creado el quinto hijo empezaremos a detectar el problema, puesto que siempre va a quedar oculta de nuestro calculo la ultima de las filas.

Finalmente, respecto a la barra de scroll horizontal, la propia lógica nos hace intuir que las respectivas asignaciones alTop de los hijos previos, harán que la referencia a ContentLayout considere el Width del contenedor padre de forma que aunque su tamaño sea superior, cualquier invocación a Realing( ) ocultaría la barra horizontal de scroll.

La función GetParentedRect, es la que nos descubre que solo considera los valores del campo Position, frente a nuestra suposición inicial de que puede ser relevante el Top o el Bottom (al menos en Firemonkey) para el caso que tenemos en mente.

function TControl.GetParentedRect: TRectF;
begin
  Result := RectF(0, 0, Width, Height);
  OffsetRect(Result, Position.X, Position.Y);
end;

¿Podemos ayudar a  Seguismundo?

Lo intenté, siguiendo los supuestos que el me comentaba.

8-)

A vuelta de correo le enviaba unas lineas de código, que básicamente hacían lo que el me había comentado pero en su lugar, dejaba el valor de Align del componente hijo en el valor por defecto, alNone, de forma que los cálculos resultantes siempre considerasen el área y posición de los hijos. La altura y desplazamiento adecuado, quedaba calculado en función del valor de ContentLayout actual, como podréis ver en el código, que adjunto en la parte inferior.

El código intenta corregir algunas de las cosas que comentábamos. Ahora el componente que representa la fila no va a descender de TObject sino que va a ser el propio layout. La variable de clase que identificaba la fila ahora había sido sustituida cediendo dicho control a un descendiente del contenedor padre, creado interponiendo la clase. Y sucesivos detalles.

Este es el código que envié a Seguismundo, que contiene un modulo de interfaz y una unidad con la declaración de los componentes:

 

unit UMainSampleScrollBoxFMX;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
  FMX.StdCtrls, FMX.Layouts, FMX.Objects, UClassGrillaTest;

type
  TfmTestScrollBox = class(TForm)
    btnTestScrollBox: TButton;
    ScrollBox1: TScrollBox;
    panTest: TPanel;
    lbAuthor: TLabel;
    procedure btnTestScrollBoxClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  fmTestScrollBox: TfmTestScrollBox;

implementation

{$R *.fmx}

procedure TfmTestScrollBox.btnTestScrollBoxClick(Sender: TObject);
begin
  ScrollBox1.AddRowLabels(Random(10)+1, Random(20)+30, Random(40)+20);
end;

procedure TfmTestScrollBox.FormCreate(Sender: TObject);
begin
  Randomize;
end;

end.

 

Esta es una imagen del formulario de la interfaz.

formulariotest

 

Y finalmente, la unidad que contiene las clases que representan a las filas, que yo he llamado TRowLabels.

 

unit UClassSampleScrollBoxTest;

interface

uses System.Classes, FMX.Layouts, FMX.StdCtrls, FMX.Types, FMX.Objects;

type
  TRowLabels = class;

  TScrollBox = class(FMX.Layouts.TScrollBox)
  private
    FRowLabelsArray: array of TRowLabels;
  public
    function AddRowLabels( AColumnCount: Integer; AWidth, AHeight: Single): TRowLabels;
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

  TRowLabels = class(TLayout)
  protected
    function CreaEtiqueta(ARowIndex, AColumnIndex: Integer; AWidth, AHeight: Single): TLabel; virtual;
    procedure Paint; override;
  public
    constructor Create(AOwner: TComponent; AIndexRow, AColumnCount: Integer; AWidth, AHeight: Single);
  end;

implementation

{  TRowLabels }

uses System.SysUtils, FMX.Dialogs, System.Types;

function TRowLabels.CreaEtiqueta(ARowIndex, AColumnIndex: Integer; AWidth, AHeight: Single): TLabel;
begin
   Result:= TLabel.Create(Self);
   with Result do
   begin
     Parent:= Self;
     Name:= 'F'+ IntToStr(ARowIndex)+'C'+IntToStr(AColumnIndex);
     Width := AWidth;
     Height:= AHeight;
     Align := TAlignLayout.alRight;
     AutoSize := False;
     Text := Name;
     Align := TAlignLayout.alMostLeft;
   end;
end;

constructor TRowLabels.Create(AOwner: TComponent; AIndexRow, AColumnCount: Integer; AWidth, AHeight: Single);
var
  FColumnCount: Integer;
begin
  inherited Create(AOwner);
  Name:= 'lyRow'+IntToStr(AIndexRow);
  Width:= AColumnCount * AWidth;
  Height:= AHeight;
  Position.X:= TScrollBox(AOwner).ContentBounds.Left;
  Position.Y:= TScrollBox(AOwner).ContentBounds.Height;
  FColumnCount:= AColumnCount;
  while (FColumnCount > 0) do
  begin
     CreaEtiqueta(AIndexRow, AColumnCount-FColumnCount+1, AWidth, AHeight);    
     Dec(FColumnCount);
  end;
   Parent:= AOwner as TFmxObject;
end;

procedure TRowLabels.Paint;
var
  R: TRectF;
begin
  inherited;
  if not (csDesigning in ComponentState) then
  begin
    R := LocalRect;
    InflateRect(R, -0.5, -0.5);
    Canvas.DrawDashRect(R, 0, 0, AllCorners, AbsoluteOpacity, $A9999999);
  end;
end;

{ TMyScrollBox }

function TScrollBox.AddRowLabels( AColumnCount: Integer; AWidth, AHeight: Single): TRowLabels;
var
  i: Integer;
begin
  i:= Length(FRowLabelsArray);
  Inc(i);
  SetLength(FRowLabelsArray, i);
  FRowLabelsArray[i-1]:= TRowLabels.Create(Self, i, AColumnCount, AWidth, AHeight);
  Result:= FRowLabelsArray[i-1];
end;

constructor TScrollBox.Create(AOwner: TComponent);
begin
  inherited;
  SetLength(FRowLabelsArray, 0);
end;

destructor TScrollBox.Destroy;
begin
  SetLength(FRowLabelsArray, 0);
  inherited;
end;

end.

La ejecución mostraba que los cálculos eran ahora correctos. Esta es una captura de la misma. Se la envié a mi amigo Seguismundo junto el proyecto por si hubiera podido ayudarle. Para las pruebas, había asignado valores aleatorios tanto a la cantidad de columnas a crear como al ancho o altura de cada una de ellas, representada en esa etiqueta que muestra la posición FilaXColumna en el text (F1C1 representa la fila 1 columna 1 por ejemplo).

 

TestFinal

 

Descarga el código fuente

 

 Vuelta a la realidad

Espero que estas anécdotas de verdad os puedan servir de acicate para que tengáis la misma o mayor curiosidad que yo mismo por seguir aprendiendo día a día. No importa quien os diga que no podéis llegar mas lejos.

Tenemos una buena herramienta en nuestras manos. Yo diría que la mejor, pero es verdad que siempre esperamos que lo mejor sea lo que pueda venir el día de mañana.

También tenemos una buena Comunidad, que se ha esforzado por no quedarse atrás.

Yo encuentro muchas razones para seguir con Delphi pero no deja de ser mi opinión personal.

He dejado para el final el comentar todo el tema de la promoción de final de año y mientras finalizaba el articulo, recibía el correo de Danysoft que concretaba en nuestro idioma el contenido de la oferta, haciendo que no necesite traducir el texto original en ingles de Embarcadero.

jover1000x125

La oferta finaliza el 31 de Diciembre de este año.

Entérate de las 5 razones para dar el salto a Rad Studio XE5
Razón 1 | Actualiza desde cualquier versión anteriorFour special offers on RAD Studio, Delphi and C++Builder XE5.
Razón 2 | Bonus Pack gratuito valorado en +1300€
Razón 3 | Bonus Pack exclusivo Danysoft
Razón 4 | Edición Ultimate al precio de Enteprise
Razón 5 | Descuento adicional en 2 o + licencias, o mantenimiento

En el enlace de la imagen, podéis encontrar detalles ampliados de esta oferta que como compartía con vosotros al incoo me parecía interesantes.

Me despido de vosotros y de mi amigo Seguismundo, buen camino.

enlared

Leído y destacado en el blog de Marco Cantú…

Source Code of DataSnap Android Client – Autor: Marco Cantú
FUENTE: Su Blog (http://blog.marcocantu.com/blog/source_code_datasnap_android_client.html)

Traducción:

Escribía sobre el área cliente de DataSnap en móviles en Agosto y lo mostraba en CodeRage y otras conferencias. La entrada original del blog se encuentra en: blog.marcocantu.com/blog/datasnap_android_clients.html y ya incluía la imagen que mostrada mas abajo. Ahora he añadido el código fuente a mi repositorio “Embarcadero Sessions Repository” en code.marcocantu.com/.

La demo muestra como ejecutar una simple operación “reverse string” en el servidor y como acceder a un dataset remoto (un archivo CDS local al servidor), cargarlo en un tabla en memoria y usar livebindings en un control ListView (con agrupamiento y una cabecera). El actual código cliente tiene dos lineas y se encuentra disponible en:
code.marcocantu.com/trac/marcocantu_delphi_sessions_demos/browser/datasnap/DataSnap101/DSMobileClientForm.pas#L45.

Enlazar el proyecto en el código del repositorio para el acceso a través de subversión o navegar por las fuentes en el enlace superior.

PS. En otras demos que escribiré pronto mostraré como usar Firedac tanto en el cliente y servidor y como usar RESt en lugar de la interfaz IAppServer/Provider como en esta demo se muestra.

PS 2: ¿Cuántas herramientas de desarrollo móvil te permiten ver datos en vivo en tiempo de diseño?

 

 

image002

Próximos eventos X5 en España y Portugal y Update 1 para XE5

image002

¡Amigos!

¡Hay novedades para España y Portugal!

A partir del 13 de Noviembre se inicia una muy interesante gira de Danysoft para Delphi y Rad Studio XE5; bastante ambiciosa porque se amplían las ciudades que van a visitar y que van a tener el privilegio ( y lo escribo en negrita para resaltarlo) de conocer de primera mano la novedades de  la ultima versión de Delphi. En ese sentido, mi felicitación a los responsables y equipo técnico porque año a año van ampliando las ciudades fuera de las que han sido clásicos destinos de estas presentaciones, como Madrid o Barcelona. Tener al frente de estas presentaciones al MVP de Embarcadero, Luis Alfonso Rey, es una garantía de que el evento va a ser de primera.

:-)

Si alguno de los compañeros le interesa, comento que voy a intentar estar en Murcia, si el trabajo me lo permite. Ha sido un verdadero placer  las ocasiones que estos eventos me han dado oportunidad de conocer compañeros que han compartido las actividades de la comunidad, casi siempre a través de los sitios públicos que todos conocemos. En general, conocer a otros programadores, con inquietudes y motivaciones distintas o similares de las que te puedan mover, es algo enriquecedor  a todos los niveles: personal, profesional, etc..  y estos eventos, nos dan la oportunidad de salir del circulo cerrado en el que muchas veces nos movemos.

Esta es la relación de seminarios que se van a celebrar:

Podeis ampliar la información en la web de Danysoft: Ir a la pagina

 

Por otro lado, os comento que ya disponéis del primer Update de XE5,

ID: 29595, Update 1 for RAD Studio XE5, Delphi XE5 and C++Builder XE5

Acceded al area de embarcadero, con vuestros datos de usuario registrado para descargarlo en el enlace anterior.

La lista de correcciones la podéis leer en:

Fix list for Update 1 for RAD Studio XE5, Delphi XE5 and C++Builder XE5

Mas información: +Info

Dos muy buenas noticias las que hemos compartido en esta entrada: por un lado, la continuidad de estos seminarios gratuitos en otros puntos de España dentro de la actividad desplegada por el partner español, y por otro, la siempre buena noticia de que Embarcadero siga con las correcciones para hacer mas estable y productiva la nueva versión.

¡Buen camino a todos!

 

 

 

 

CodeRage8_159x228_RN

Preparados para vivir CodeRage 8

Se va a vivir en pocos días.   :-D

Me parece una noticia ¡tan fantástica!, que este blog, que siempre quiere estar cerca de vosotros, no podía menos que hacer un alto para resaltarla.

CodeRage 8, hermana de otros tantos eventos anteriores, CodeRage 7, CodeRage 6, CodeRage 5, etc… abrirá sus sesiones de trabajo desde el 15 de Octubre hasta el 17.

NewCodeRage8_680x150_RN

A la vuelta de la esquina, como quien dice…

Son tres días con una agenda de sesiones que vale la pena revisar. En el siguiente enlace podéis encontrar el detalle de las mismas.

Agenda del evento

Le he estado dando un vistazo y se abordan muchos temas que sobre los que existe gran interés. Firedac es uno de ellos pero también la programación con Android, Fast Reports, o lo que refiere a las apis tanto de iOS como de Android.

Os aconsejo que deis un vistazo a las sesiones de cada día, que son muchas.

Algunas preguntas que os podéis estar haciendo…

P. ¿Debería asistir a ese evento on line?
R. Desde luego. Es muy recomendable. Las personas que llevan ligadas tiempo a la Comunidad saben que se deben aprovechar siempre todos los recursos que se pongan al alcance, mas cuando, como éste, son eventos gratuitos. Embarcadero es consciente de la necesidad de que se organicen y pone el máximo celo en su calidad y que sean conocidos por todos y lleguen a todos los lugares de la Comunidad Global. Por ello, los ponentes son conferenciantes y profesionales de nuestra herramientas de primer orden,

P.Pero las conferencias son en Ingles. No me enteraré de nada. Es una tontería asistir…
R. Ehhhh… Reconozco que muchas veces es un aspecto que desanima, y que hace que muchos compañeros no se inscriban, pero en un mundo como el nuestro tan competitivo tenemos que ponernos las pilas y dar siempre un paso adelante.  Las sesiones tienen un gran apoyo, como no podía ser de otra forma, en los recursos visuales, por lo que en muchos casos, con un nivel de ingles medio pueden ser seguidas con mas o menos dificultad. Es una cuestión de actitud.

;-)

P. No podré asistir a todas las conferencias. Son muchas.
R. Durante los días sucesivos estarán disponibles todas las sesiones del evento, al igual que en años anteriores. Si hay alguna sesión en la que tengas interés especial puedes visitar nuestros blogs, en facebook delphisolidario o en delphispano, porque seguro que iremos publicando los enlaces para que puedas encontrarlos fácilmente.

P. ¿Pero… de verdad valen la pena?
R. Sí. Son 39 sesiones de 45 minutos. Gratuitas… No hablamos de una presentación comercial sino un evento de trabajo con una agenda bastante apretada para los tres días. A veces resulta complicado sacar tiempo durante el horario de trabajo para poder asistir a estas conferencias técnicas pero creo que no deberíais perder la repetición posterior.

Así que apuntad los días 15, 16 y 17 de Octubre en vuestra agenda, porque CodeRage 8 va a ser un gran evento.

 

explorador

Rad Studio XE5: Tip de ayuda al inicio

Hoy quería compartir con vosotros un breve pero creo que útil tip, o consejo.

Cuando todo marcha bien…

Lo habitual, lo normal, sería que tras la instalación de RAD Studio XE5, estuvieseis en condiciones de tener esa primera experiencia con Android y en un porcentaje alto de los casos va a ser así.

:-)

Y además, con un alto porcentaje también, valga la redundancia, de que esta primera experiencia sea satisfactoria. Son muchos los compañeros del foro que han referido como algo positivo y no han narrado, o compartido con el resto de compañeros, problemas en lo que atañe a la configuración de los dispositivos. Mas al contrario, una buena parte de los comentarios leídos inducir a pensar que es así.

De hecho, la instalación del entorno de desarrollo se ocupará de los detalles de instalación y configuración de las herramientas de desarrollo de Android, que incluyen el sdk (software development kit) y el ndk (native development kit), al menos si dejamos marcados los checks de selección durante el proceso de instalación, ahorrándonos todo ese trabajo. Eso es algo que hemos comentado ya en entradas anteriores y existe buena documentación sobre estos puntos para enfrentarnos al momento de esa primera aplicación para Android. Existe además un vídeo de Danysoft que recomendábamos en la entrada anterior y que narraba los pasos a seguir.

De lo leído en la docwiki me quedaría con algunos enlaces que son necesarios en esa primera toma de contacto. Básicamente entiendo que son tres:

Todo ello en la docwiki de Embarcadero. Si la versión de Android de vuestro dispositivo pertenece a la relación de versiones soportadas, que podéis consultar en el ultimo  enlace, y se ha configurado el adecuado driver usb, que va a permitir que exista comunicación con él, no debería existir mayor problema para que podáis reconocerlo en el explorador del proyecto dentro del nodo destino. Basta habilitar en el dispositivo, habitualmente en la zona de ajustes, el área de desarrollador, marcando como la depuración usb, para que se habilite el canal de comunicación. Depende ya de cada dispositivo la ubicación de este permiso.

Eso sería lo habitual o lo normal, como queráis.

Cuando las cosas no marchan bien…

Es inevitable…

:-)

Siempre hay alguna circunstancia especial, que rompe con esa buena marcha y yo quería compartir con vosotros una en concreto que me afectó en los primeros días como betatester de XE5, por si fuera el caso que os pueda ayudar en otro momento posterior.

En mi caso, de cara a mi participación en la beta, disponía dos dispositivos Android, de forma que iba a probar las aplicaciones con dos tamaños distintos de pantalla y con diferencias en cuanto a sus especificaciones. El primero se correspondía con un móvil S3 Galaxy Mini, con un tamaño de pantalla de 4″. En cuanto al segundo dispositivo era un tablet de Airis, Onepad 1100×2 de 10″. Además ambos eran compatibles con las versiones de Android (el primero se correspondía con la 4.1.2 y el segundo con la 4.1.1, ambas JellyBean, y dentro de la lista de posibles destinos). Es decir que en ese sentido, ambos dispositivos cumplían con parte de las condiciones, de forma que podría prescindir del emulador que como sabéis es extremadamente lento.

Una vez, había instalado el entorno de desarrollo, la instalación del driver usb en el caso del móvil de Samsung se podía hacer simplemente a través del programa Kies facilitado por la misma empresa -Samsung-, que permite la sincronización de archivos entre el pc y nuestro dispositivo. Así que era una tarea trivial ya que una vez hecho este paso, la misma instalación del software configura la versión del driver usb, y una vez añadido en el área de configuración de Delphi el sdk de trabajo, el entorno quedaba capacitado para detectar el nuevo dispositivo, simplemente refrescando el nodo que trae por defecto los dos emuladores de Android que fueron añadidos con la instalación.

En ese sentido, los primeros pasos con Android fueron muy satisfactorios en el S3 ya que pude ejecutar y depurar pequeños ejemplos sin mayores problemas.

Con el tablet fue otra historia porque para empezar no era detectado correctamente en el proceso de instalación del dispositivo y mostraba una advertencia en el administrador de dispositivos de windows. De hecho, esto me obligó a buscar en los foros de Airis y a perder bastante tiempo y existían numerosas peticiones o preguntas sobre este tema y en muchos casos se remitían finalmente al uso del driver genérico de Google, aunque existían unos drivers del fabricante que funcionaban en unos modelos pero en otros no. En mi modelo de tablet,  al menos en ese momento, no existían drivers adecuados. Así que tuve que buscar información, principalmente en google y me pareció bastante imprescindibles dos enlaces:

Google USB Driver y OEM USB Drivers.

El primero era interesante porque indicaba como descargar e instalar el driver usb de Google, además de indicar detalles de los modelos que incluye, básicamente los relacionados con la empresa. Y el segundo refiere la instalación en el dispositivo, localización de la carpeta en nuestro sistema tras la descarga.

Para que el sistema instale y reconozca el driver de Google para ese dispositivo, es necesario que modifiquemos el fichero android_winusb.inf, ubicado en la carpeta donde se encuentra el sdk de Android, dentro del directorio “extras”:  <sdk>\extras\google\usb_driver. Necesitamos añadir un par de lineas conteniendo el VendorID y el ProductID del dispositivo.

Para ello, podemos buscar ambos datos en la pestaña de detalles de las propiedades del dispositivo. En este caso, como veis por la imagen, ya tenía localizados a través del ID. de Hardware los valores VID 2207 y PID 0010.

info

 

Seguimos…

Lo siguiente fue añadir las dos lineas inferiores, con la estructura adecuada usando dichos valores, siguiendo el mismo patrón que descubre el resto de lineas leídas en el fichero para otros dispositivos:

 %SingleAdbInterface% = USB_Install, USB\VID_2207&PID_0010
 %CompositeAdbInterface% = USB_Install, USB\VID_2207&PID_0010&MI_01

Por lo tanto, teniendo en cuenta que hay una sección en el fichero para 32 bits y otra para 64 bits, os muestran a continuación como quedó parte de ese fichero (las he remarcado en color en cada sección):

[Google.NTx86]
;Google Nexus One
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_0D02
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_0D02&MI_01
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E12&MI_01
;Google Nexus S
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E21
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E22&MI_01
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E23
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E24&MI_01
;Google Nexus 7
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4E40
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E42&MI_01
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E44&MI_01
;Google Nexus Q
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_2C10
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_2C11
;Google Nexus (generic)
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2&MI_01
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE4&MI_02
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE6&MI_01
;OnePad 1100x2
 %SingleAdbInterface% = USB_Install, USB\VID_2207&PID_0010
 %CompositeAdbInterface% = USB_Install, USB\VID_2207&PID_0010&MI_01
[Google.NTamd64]
;Google Nexus One
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_0D02
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_0D02&MI_01
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E11
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E12&MI_01
;Google Nexus S
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E21
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E22&MI_01
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_4E23
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E24&MI_01
;Google Nexus 7
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4E40
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E42&MI_01
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4E44&MI_01
;Google Nexus Q
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_2C10
 %SingleAdbInterface% = USB_Install, USB\VID_18D1&PID_2C11
;Google Nexus (generic)
 %SingleBootLoaderInterface% = USB_Install, USB\VID_18D1&PID_4EE0
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE2&MI_01
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE4&MI_02
 %CompositeAdbInterface% = USB_Install, USB\VID_18D1&PID_4EE6&MI_01
;OnePad 1100x2
 %SingleAdbInterface% = USB_Install, USB\VID_2207&PID_0010
 %CompositeAdbInterface% = USB_Install, USB\VID_2207&PID_0010&MI_01

Y casi fin de la historia…

:-)

La instalación ya mostraba correctamente los dos dispositivos en el administrador del sistema. Os incluyo esa imagen:

administrador_dispositivos

Pero falta un punto.

Nos queda modificar el fichero adb_usb.ini,  en donde vamos a añadir el VID, para lo cual podemos usar la consola (previamente ya hemos conectado mediante cable usb) :

  1. adb kill-server
  2. echo 0x2207 >> "%USERPROFILE%\.android\adb_usb.ini"
  3. adb start-server
  4. adb devices

Tras esto, se debería solventar el problema. El ultimo comando debería retornar una lista de todos identificadores que representan los dispositivos conectados, tanto fisicos como emuladores, y a partir de este momento, podríamos identificar los dispositivos en el nodo adecuado de Delphi, como se puede ver en la imagen inferior.

Tenéis amplia información de los distintos comando que podéis utilizar con el adb de Google. La podéis encontrar en:

http://developer.android.com/intl/es/tools/help/adb.html

explorador

Espero que pueda ser de ayuda a los compañeros de la comunidad en algún momento.

Saludos y buen camino.

 

 

radstudioxe_bannershop

Lanzamiento de Rad Studio XE5: ¡No te quedes atrás!

radstudioxe_bannershop

Hola:

A lo largo del día de ayer e imagino que también en los días sucesivos, los distintos blogs de la Comunidad nos haremos eco del lanzamiento de XE5, que como ya sabéis, viene marcada por abrir las puertas al desarrollo de aplicaciones móviles para Android. No es que sea la única novedad de esta versión, sino que digamos es la que eclipsa por méritos propios al resto de novedades.

:-)

No. No me queda la menor duda de que esto es así…

¡Es una gran semana! ¡Muy esperada! Hay en el ambiente algo de agitación, de preparativos. Todo tiene que estar a punto para celebrarlo. Ayer compartía unas lineas de correo con Jose Luis Castaño de Danysoft, empresa partner de Embarcadero para nuestro país y Portugal, y me comentaba que se esperaban ¡muchas! inscripciones en los próximos eventos que vamos a disfrutar, que os recuerdo van a tener lugar en Barcelona, Madrid y Portugal, en los últimos días del mes de Septiembre (25, 26 y 27 respectivamente). Porque existe gran expectación. Los compañeros quieren conocer el producto y saben que asistir al evento de presentación da la oportunidad de vivir un poco mas de cerca esos detalles. Si me aceptáis un consejo: No dejéis para última hora la inscripción y que no se os haga tarde, porque las plazas suelen ser limitadas y creo que este año va a existir mayor asistencia en estos eventos de presentación.

xe5_jover1000x125

Volvemos a tener el protagonismo. Embarcadero sigue terco en marcar el camino que nos brinda una herramienta capaz de manejarse en múltiples plataformas con un desarrollo verdaderamente nativo, con altas prestaciones; que ciertamente no es gratuita pero que promete rentabilizarla con nuestra productividad. Tenemos a nuestro alcance, con XE5, juntas las plataformas moviles de Android e iOS. Seguimos teniendo Windows en 32 y 64 bits. Y tenemos también OSx.

Otro de los motivos por los que contacté con Jose Luis Castaño fue para, en próximos días, informaros desde el blog de las ofertas y el valor añadido de Rad Studio XE5, algo se ha convertido ya una tradición en el blog de Delphi Básico con motivo de las presentaciones.

Comparto también con vosotros que estoy preparando esa segunda parte de la entrada anterior (estoy en ello) para ver con mas detalle aspectos concretos de las novedades, y posiblemente la podamos ver a lo largo del fin de semana aunque no lo puedo asegurar; pero no quisiera despedir la entrada sin comentar que he vivido durante estos últimos meses y he seguido muy de cerca la fase final de la beta de XE5, con emoción, disfrutando durante el tiempo que ha estado abierta, de los esfuerzos y el empeño de todos los participantes para que tengamos no una versión mas, sino la mejor versión. Felicidades a todos por el gran trabajo que habéis hecho desde esa trinchera que se convierte el área de betatesters y felicidades a Embarcadero por esta nueva versión.  Ha sido una experiencia fascinante y enriquecedora. Yo al menos la he vivido así.

No os perdáis el vídeo de Danysoft, sobretodo si tenéis pensado descargar durante estos días la versión trial, ya que se comentan  temas de la instalación y configuración del producto que no os vendrá nada mal para dar esos primeros pasos en el entorno.

Lo dicho. ¡Felicidades Embarcadero! Creo que se ha hecho un grandísimo trabajo.

¡Nos vemos en la próxima entrada y Buen camino!

 

Imagen Parallels

Primeros pasos con RAD Studio XE5 – Parte I

Retomamos la actividad en el blog, que desgraciadamente tuve que interrumpir por motivos de trabajo y lo hacemos a lo grande… con la primera entrada en la que vamos a poder conocer unas pinceladas de XE5, que es la primera versión de Delphi para la plataforma Android.

:-)

Se que eso va a ser de agrado para muchos compañeros que desean conocer algo del próximo lanzamiento, y dado que Embarcadero nos ha autorizado, dentro del programa de MVPs, para poder compartir desde nuestros blogs esas primeras impresiones que hemos recibido a traves de las betas, me parecia la mejor forma de reencontrarme con vosotros.

Realmente no he estado alejado de la Comunidad, ya que he seguido participando activamente dentro del Proyecto Delphispano, y en el marco del foro de Delphi Solidario en Facebook. Pero es verdad que no he podido atender todo lo que quisiera mi propio blog. No obstante creo que ha valido la pena esperar.

Para esta primera entrada había preparado unas capturas dentro de un powerpoint y finalmente, por temas de espacio en el video, se omitieron con la idea de mostrarlas en esta entrada. Las imágenes muestran algunas ideas que me parecen importantes respecto a las novedades.

Esta es la primera idea importante:

Diapositiva2

Viene a expresar que la herramienta que ya soporta múltiples plataformas, nos va a ofrecer un marco común de trabajo capaz de permitirnos trabajar con transparencia sobre muchos de los objetos propios de cada plataforma, de forma que una misma base de código va a permitirnos compilar para distintos dispositivos y plataformas.

Logicamente, cada una de ellas, luego tendrán sus peculiaridades, y eso no nos va a eximir de conocerlas. Ese marco común es por supuesto: Firemonkey.

En este punto os invitaría a la lectura de las cuatro entradas del blog de Delphi en Movimiento, donde nuestro buen amigo Eliseo, compartió con la comunidad, como Delphi nos permitirá que un mismo proyecto pueda ser compilado en distinta plataformas y dispositivos con los mínimos cambios.

Tenemos un entorno de desarrollo multiplataforma, que suma una gran opción a las que ya teníamos, como lo es Android.

Rad Studio XE5 trae muchas mejoras a nivel de IDE que nos van a ayudar a incrementar nuestra productividad. Una de esas mejoras que a mi particularmente me parece genial, es el nuevo explorador de proyectos.

Esa idea se captura en la siguiente imagen, que nos muestra distintos nodos nuevos, concretamente el nodo TARGET, del cual van a colgar los dispositivos vinculados al destino seleccionado. En el nodo habilitado para Android podremos tener conectados los distintos dispositivos sobre los que vayamos a trabajar y alternarlos de una forma tan sencilla como es la selección de uno de ellos. En el video se aprecia claramente esto.

Personalmente me ha parecido muy acertado este cambio. Es de las cosas que mas me han gustado.

Diapositiva3

 Pero hay mas mejoras y Rad Studio viene con muchas mas novedades. Una de esas novedades, en la linea de incrementar la productividad de nuestro trabajo en el IDE es la nueva disposición de IDE Insight, reubicado en una zona mas accesible y separado de la ventana de dialogo, ahora ofrece mayor funcionalidad de cara a nuestro uso frecuente.

Diapositiva4

Rad Studio también ha mejorado el mismo marco de trabajo con iOS y Android en la gestión de Deploy, que además frente a XE4, nos permitirá seleccionar múltiples archivos. Un interfaz mejorado buscando que se incremente la productividad en esas tareas de configuración del dispositivo.

Diapositiva5

Aunque aquí no se vea reflejado, y para que se pueda entender esta idea, la asistencia de nuestro Entorno empieza con la instalación de los SDK y NDK adecuados a la versión actual de desarrollo de forma que tras esa instalación de XE5, nuestro entorno quedará configurado en todas la rutas de gestión de librerías. Esa idea que ya la podíamos encontrar en XE4 cuando descubríamos la facilidad de configurar el marco de trabajo, ahora la volvemos a descubrir con Android. En próximas entradas será algo que podamos ver y comentar.

Otro tema que forma parte de las novedades, viene de la mano de Android el el uso que hace esta plataforma de los permisos a nivel de aplicación.

Ahora podemos encontrar en la zona de opciones de proyecto un área de permisos de usuario donde vamos a configurar con un verdadero//falso los distintos permisos que van a ser dispuestos. En la programación de Android supondría que deberíamos en muchos casos escribir en el Xml del archivo de manifiesto de la aplicación, cada uno de estos permisos. Es una cosa que a mi me ha encantado y me ha parecido una gran idea.

Diapositiva6

 

Hay mucho mas y muchos detalles para comentar. Tendremos tiempo para compartirlos. Quedaban enumerados en la imagen inferior.

La llegada de Android implica cambios. Algunos mas importantes otros. Pero creo de verdad que vale la pena.

Diapositiva7

Finalmente, he preparado un pequeño video donde se puede ver un cliente datasnap para firemonkey y simultáneamente, el mismo cliente compilado con iphone. Para hacerlo lo mas simple posible, solo vamos a ejecutar uno de los métodos que por defecto trae la plantilla de datasnap, el método EchoString() que retorna la misma cadena que hemos enviado, pero creo que eso ya nos permitirá valorar las posibilidades que abre todo lo que encierra esta tecnología dentro de las plataformas móviles.

A mi, al menos, me parece francamente prometedor el abanico de posibilidades que disponemos en cuanto a datos: DataSnap, SqlLite, Interbase, Firedac.

El video, también incluye una pequeña demos donde se muestra algo característico de la plataforma Android, como puede ser el uso de los Intent. Embarcadero está haciendo un trabajo enorme que se puede apreciar cuando se recorren las unidades que encapsulan los objetos propios de Android.

En ese sentido me siento francamente convencido de que estamos en un camino correcto. Quizás un poco tarde para las necesidades que teníamos de incorporar Android a nuestros desarrollos pero no me queda duda de que ha valido la pena esperar. Creo que nunca ha sido tan fácil hacer una aplicación tanto para Android como para iOS y las que puedan venir en adelante.

Por eso mi pregunta…

¿De verdad te la vas a perder?

:-)

Me despido para preparar nuevas entradas que os puedan ser de ayuda antes del lanzamiento.

Espero que os guste y que hayais disfrutado de este rato que hemos compartido.

Podeis encontrar mas información en la web de Embarcadero:

Get Ready to Create Android Apps with RAD Studio

Diapositiva8


Enlaces relacionados que no os deberíais perder:

Sneak Peek of Delphi XE5: Android DataSnap
Posted by  on 21-Aug-2013


 

 

Algunas reflexiones y comentarios sobre Delphi