cómo hacer una galería de imágenes con FWH

Desde hace mucho tiempo he querido incorporar una galería de imágenes a algunos de mis programas. Esto data de mis tiempos de fanboy de Apple, cuando quedé prendado de un programa llamado Delicious Library al que me referí en esta entrada.

El caso es que hace poco estaba dándole vueltas a la cabeza en la manera de hacerlo y pregunté en el foro de FWH. La primera intención fue crear una clase a medida dentro de una ventana, pero esa solución no me valía porqué el flujo del programa es muy complicado de controlar pues las ventanas quedan independientes. Hubo otra propuesta de clase basada en diálogo utilizando la clase TPanel de FWH, y buscando ejemplos de esta clase me topé con la clase TScrollPanel que no conocía y de la que apenas hay documentación. Utilizando esta clase y el código que Mr. Rao había realizado para la clase TAlbum fue muy sencillo implementar la galería de imágenes.

Esta galería de imágenes la puedo utilizar, por ejemplo, para crear una galería de portadas de libros.

Ejemplo de galería de portadas de libros

Lo bueno de esta galería es que muestra las portadas en el orden de la rejilla de libros y si hay algún filtro activo la galería muestra unicamente los libros que aparecen en el filtro.

El código que he utilizado para crear la galería es el siguiente:

Function LiGaleria()
   LOCAL cAlias  := "LI"
   LOCAL nRecno  := ( cAlias )->( RecNo() )
   LOCAL nOrder  := ( cAlias )->( ordNumber() )
   local aImages := {}
   local aLabels := {}
   local aRecno  := {}
   local oDlgAlbum, oAlbum

   LI->(DbGoTop())
   WHILE ! LI->(EOF())
      IF ! Empty(Rtrim(LI->LiImagen))
         AAdd(aImages, Rtrim(LI->LiImagen))
         AAdd(aLabels, Rtrim(LI->LiTitulo))
         AAdd(aRecno, LI->(Recno()))
      ENDIF
      LI->(DbSkip())
   ENDDO
   LI->(DbGoTo(nRecno))

   DEFINE DIALOG oDlgAlbum SIZE oApp():oGrid:nWidth, oApp():oGrid:nHeight PIXEL TRUEPIXEL ;
      TITLE "Galería de portadas de libros - dobleclik para editar un libro"
   oDlgAlbum:SetFont(oApp():oFont)
   //
   oAlbum := TScrollPanel():New( 20, 20, oApp():oGrid:nHeight-50, oApp():oGrid:nWidth-20, oDlgAlbum, .f. )
   oAlbum:SetColor(CLR_WHITE, CLR_WHITE)
   oAlbum:SetFont( oDlgAlbum:oFont )

   @ oApp():oGrid:nHeight-40, oApp():oGrid:nWidth-96 BUTTON "Aceptar" ;
      SIZE 76, 24 PIXEL OF oDlgAlbum ACTION oDlgAlbum:End()

   ACTIVATE DIALOG oDlgAlbum ;
      ON INIT ( LiAlbum( oAlbum, aImages, aRecno, oDlgAlbum ), oDlgAlbum:Center( oApp():oWndMain ) )

   RETURN NIL  

function LiAlbum( oPanel, aPhotos, aRecno, oDlgAlbum )
   local nImgPerRow  := 8
   local nImgWidth   // := 180
   local nImgHeight  // := Int( nImgWidth * 4 / 3 )
   local nHGutter    := 10
   local nVGutter    := 20
   local nCols       := nImgPerRow 
   local nRows, nRow, nCol, x, y, nImage, xMax, nImages := Len( aPhotos )
   local oImage, oSay

   // el ancho del scrollbar es 16
   nImgWidth := INT((oPanel:nWidth-16-(nImgPerRow+1)*nHGutter)/nImgPerRow)
   nImgHeight:= Int( nImgWidth * 4 / 3 )
   nRows    := Ceiling( nImages / nCols )
   xMax     := nCols * ( nImgWidth * nHGutter )
   y        := nVGutter
   nImage   := 1
   do while nImage <= nImages
      x     := nHGutter
      nCol  := 1
      do while nCol <= nCols .and. nImage <= nImages
         // llamo a una funcion para conseguir detached locals
         LiAlbumImage(y, x, nImgWidth, nImgHeight, oPanel, aPhotos, aRecno, nImage, nVGutter, oDlgAlbum)
         nImage++
         nCol++
         x  += ( nImgWidth + nHGutter )
      enddo
      y  += ( nImgHeight + nVGutter )
   enddo
   //::nImgCols  := nCols
   // ::nHeight   := y
   oPanel:SetRange() // call this after defining all controls

return nil

Function LiAlbumImage(y, x, nImgWidth, nImgHeight, oPanel, aPhotos, aRecno, nImage, nVGutter, oDlgAlbum)
   local oImage, oSay, nLiRecno
   nLiRecno := aRecno[nImage]
   @ y, x XIMAGE oImage SIZE nImgWidth, nImgHeight OF oPanel NOBORDER
   oImage:SetSource( If( HB_ISARRAY( aPhotos[ nImage ] ), aPhotos[ nImage, 1 ], aPhotos[ nImage ] ) )
   oImage:nUserControl := 0
   oImage:lBmpTransparent := .f.
   oImage:bLDblClick := { || ( LiForm( oApp():oGrid, "edt", , nLiRecno, oDlgAlbum )) }

   //@ y+nImgHeight+(nVGutter/2), x SAY oSay PROMPT nLiRecno FONT oApp():oFont ;
   //   COLOR CLR_BLACK, CLR_WHITE ;
   //   SIZE nImgWidth, 2*nVGutter CENTER PIXEL OF oPanel
return NIL

En este código estoy utilizando tres funciones:

  • LaGaleria que recorre el fichero de libros para crear 3 arrays donde guardo las portadas, los títulos y los número de registro a que se refiere cada portada. Aquí creo el diálogo y el ScrollPanel.
  • LiAlbum donde recorro el array de imágenes para crear las imágenes dentro del ScrollPanel. Como luego quiero acceder a cada imagen para editar el libro haciendo doble click tengo que crear las imágenes en otra función utilizando la técnica de ‘detached locals’.
  • LiAlbumImage que es donde creo cada una de las imágenes, este código lo realizó Mr. Rao en el foro de FWH.

En una próxima actualización de Cuaderno de Bitácora incluiré galerías con las portadas de libros, discos y videos.

generando ficheros .rtf con harbour/fwh

Una de las opciones que trae el Puchero es la posibilidad de generar un fichero .rtf con la información almacenada de una receta. Hasta ahora el fichero .rtf que se generaba era algo como lo siguiente:

Fichero .rtf a partir de una receta… hasta ahora 😉

Para generar este fichero utilizo la clase TRtfFile de FWH que basicamente genera un fichero rtf a partir de una variable de tipo texto, pero sin permitir formateos ni muchas alegrías. Algo muy básico. La pregunta que te harás es ¿ por qué no generar un fichero docx directamente con la clase TWord o similar ? Pues porque la clase Tword para FWH requiere que el usuario tenga Word instalado, y eso es algo que evito a toda costa. La generación de ficheros XLS en mis programas la realizo utilizando la clase FileXls que Ramón Avendaño publicó en el foro de FWH hace muchos años, y que he subido a un repositorio de GitHub para evitar que desaparezca. Al generar el fichero desde cero, creando un fichero con el formato adecuado, se evita que el programa pierda funcionalidad si el usuario no tiene tal o cual programa instalado. En mi caso utilizo desde hace muchos años LibreOffice sin echar de menos ninguna funcionalidad del paquete Office de Microsoft, y los ficheros XLS los abro perfectamente con Calc.

Me puse a investigar sobre la generación de ficheros .rtf desde Harbour y FWH y encontré cosas interesantes hasta que llegué a un post en el grupo de Harbour Users en que había una clase para generar ficheros .rtf que me llamó la atención. Me puse a probarla y era lo que estaba buscando, la posibilidad de generar ficheros .rtf desde cero, creando el fichero con el formato adecuado. La clase está escrita por Thomas R. Marchione y la he publicado en Github sin tocar una coma. Espero que si el autor lee este post no haya ningún problema.

Utilizando esta clase, la exportación de receta a formato .rtf en el Puchero ahora mejora sustancialmente, puedo dar formato a los párrafos y crear tablas dentro del .rtf. Justo que lo quería.

A la hora de utilizar la clase con FWH hay que tener en cuenta lo siguiente:

  • En el fichero richtext.prg hay una instrucción #Command SET DEFAULT <x> TO <y> => <x> := IIF( HB_ISNIL( <x> ), <x> := <y>, <x> ) que genera un error debido a que FWH tiene una definición similar. Lo que he hecho ha sido cambiar esta instrucción por #Command SET RTFDEFAULT <x> TO <y> => <x> := IIF( HB_ISNIL( <x> ), <x> := <y>, <x> ) y modificar el fichero en consecuencia.
  • También hay una función FUNCTION cValToChar( xVal ) que hace reescribe otra de FWH y da problemas, en mi caso el los bitmaps de los browses aparecía NIL encima del bitmap en cuestión. En mi caso la comenté y listo.

A ver si alguien se anima a incluir posibilidad de añadir imágenes en el fichero .rtf

😉

visual studio code para harbour – II

Hace algo más de un año escribí para Harbour Magazine la entrada Visual Studio Code para Harbour, donde explicaba la configuración de VSCode para Harbour. Sin embargo, por pereza o por comodidad, seguía utilizando Hippoedit como mi editor principal. Hace pocas semanas, cosas del aburrimiento por la confinamiento, decidí restaurar Windows 10 en mi PC y reinstalar programas por aquello del mantenimiento del sistema y quitar rastros del registro. Tras la reinstalación Hippoedit comenzó a dar unos problemas extraños con la codificación de los ficheros y decidí quedarme unicamente con Visual Studio Code como único editor. Tras varias semanas de uso puedo decir que ha sido una buena decisión. Creo que VSCode es uno de los mejores editores de código que hay actualmente, y aunque haya otros editores específicos para Harbour que lo superen en cuanto al uso con este lenguaje, utilizar un único editor para todos tus proyectos en diversos lenguajes es mejor que utilizar distintos editores.

En estas semanas de uso intensivo he mejorado la configuración de VSCode para Harbour. Basicamente utilizo los mismos plugins que expliqué en la entrada anterior, pero he mejorado la configuración de las tareas de compilación y ejecución de manera que puedo compilar y ejecutar mis aplicaciones de manera cómoda y sencilla. Lo que hago es tener en cada aplicación Harbour cuatro ficheros bat que hacen lo siguiente:

  • hbformat.bat – hace una llamada a hbformat para dar formato al fichero con el que estoy trabajando. Me gusta tener una uniformidad en mi código y la mejor manera de conseguirlo es usar hbformat. El fichero contiene lo siguiente:
C:\Fivetech\hb32_bcc7_1905\bin\hbformat.exe @C:\alanit\develop\hbformat.ini %1
  • rc32.bat – llama al compilador de recursos para generar el fichero .res a partir del .rc donde están todos los formularios y bitmaps del programa. Los recursos están en una carpeta llamada recursos dentro de la carpeta del proyecto. El fichero contiene lo siguiente:
cd recursos
c:\bcc\bcc7\bin\brc32 -ic:\bcc\bcc7\include;c:\bcc\bcc7\include\windows\sdk -r puchero.rc
copy puchero.res ..
  • bh.bat – es el build de la aplicación. Llama al makefile de BCC con el fichero .mak de la aplicación. Si quieres ver el contenido de los ficheros .mak de mis programas echa un vistazo a la entrada código de alanit en GitHub. El contenido del fichero – tachán, tachán 😉 – es el siguiente:
C:\BCC\BCC7\bin\make.exe -f makefile\pch1905.mak
  • go.bat – ejecuta la aplicación.
puchero.exe

Todos estos bats se llaman desde el fichero tasks.json del proyecto que contiene lo siguiente:

{
	// See https://go.microsoft.com/fwlink/?LinkId=733558
	// for the documentation about the tasks.json format

	"version": "2.0.0",
	"tasks": [
		{
			"label": "hbformat",
			"type": "shell",
			"command": ".\\hbformat.bat",
			"args": [
				"${file}"
			],
			"presentation": {
				"echo": true,
				"focus":true,
				"reveal": "always"
			},
			"problemMatcher": [
				"$harbour"
			]
		},
		{
			"label": "brc",
			"type": "shell",
			"group": "build",
			"command": ".\\rc32.bat",
			"presentation": {
				"echo": true,
				"focus":true,
				"reveal": "always"
			},
			"problemMatcher": [
				"$harbour"
			]
		},
		{
			"label": "build",
			"type": "shell",
			"group": "build",
			"command": ".\\bh.bat",
			"presentation": {
				"echo": true,
				"focus":true,
				"reveal": "always"
			},
			"problemMatcher": [
				"$harbour"
			]
		},
		{
			"label": "run",
			"type": "shell",
			"command": ".\\go.bat",
			"presentation": {
				"reveal": "never"
			},	
			"problemMatcher": [
				"$go"
			]
		}
	]
}

Además, usando el plugin Tasks-Here las tareas del proyecto me aparecen en la barra de estado (1) de manera que puedo lanzar las tareas haciendo click sobre ellas. A la derecha de las tareas aparecen el proyecto con el que estoy trabajando y puedo cambiar de proyecto desde ahí o desde la barra lateral.

Otro plugin que he comenzado a utilizar es Bookmarks que me permite añadir marcas a mi código para luego moverme por el código con facilidad. Mas marcas se muestran en la barra lateral agrupados por el fichero que las contiene y es muy fácil moverse entre ellas.

La elección de un editor de código es algo muy personal, cada programador tiene unos motivos u otros para realizar su elección. Yo actualmente estoy usando VSCode y me encuentro muy a gusto trabajando con él. No digo que sea mejor ni peor que otros editores, pero sí que se puede trabajar prefectamente con él utilizando Harbour.

código de alanit en GitHub

He publicado en Github el codigo fuente de algunos de los programas disponibles en mi sitio web https://www.alanit.com. Estos programas están hechos con Harbour y FiveWinHarbour y creo que constituyen un buen punto de partida para cualquier programador que quiera iniciarse o profundizar en el conocimiento de estos lenguajes.

En el blog de mi web personal hay cientos de artículos sobre programación https://www.alanit.com/category/programacion y de aspectos relacionados con mis programas https://www.alanit.com/category/alanit/ que he ido publicando desde el año 2003.

Cuaderno de Bitácora

Imagen de Cuaderno de Bitácora

el Puchero

Findemes

Imagen de Findemes

El código fuente de Colossus, mi programa de gestión de contraseñas, también se encuentra publicado desde hace tiempo en https://github.com/JoseluisSanchez/colossus

Harbour Magazine

En febrero de este año comencé la publicación de Harbour Magazine, una publicación dedicada al lenguaje de programación Harbour.
Es por ello que este blog ha estado un tanto abandonado, pues he estado publicando allí información acerca del lenguaje Harbour. Harbour Magazine es bilingue español/inglés, es la primera vez que hago algo así y está siendo una gran experiencia.

Los post publicados hasta ahora han sido los siguientes:

Con Harbour Magazine ya son tres los sitios web donde publico: el blog de alanit, cincomundos y Harbour Magazine. Sinceramente no me gusta nada tanta dispersión de contenidos así que estoy pensando seriamente en unificar todo en un único sitio. Veremos como lo hago.

Diseño plano

Este artículo fue publicado también en Harbour Magazine.

El diseño plano o flat design ha sido una tendencia en diseño web en los últimos años, pero con la llegada de Windows 10 se ha impuesto también en cuanto a interfaces de sistemas Windows. El diseño plano se caracteriza basicamente por:

  • Ausencia de texturas, sombras, gradientes, biseles o cualquier otro elemento que provoque sensación de profundidad.
  • Diseño minimalista, donde los elementos respiran y no se amontonan uno encima del otro.
  • Uso de formas geométricas simples (cuadrados, rectángulos, círculos, etc.) para estructurar la información o diseñar elementos de la interfaz (botones, iconos, etc.).
  • Uso de colores uniformes, vibrantes.

Como programadores de aplicaciones en un entorno gráfico como Windows, debemos preocuparnos de que nuestras aplicaciones sigan las reglas de interfaz del entorno, de otra manera su aspecto quedará totalmente desfasado. En función del tipo de software que realicemos esto tendrá todavía más importancia, no es lo mismo desarrollar sistemas por encargo que los usuarios tienen que usar de manera obligatoria que desarrollar aplicaciones a la venta por internet donde la primera impresión al usuario será determinante en el proceso de compra. Si quieres que tu aplicación se vea bonita debes siempre seguir las reglas del interfaz del sistema operativo en que se ejecuta. Un diseño simple y funcional es la clave para tener éxito.

En mi caso, como programador de aplicaciones Windows, he modificado mis aplicaciones para dotarlas de un diseño plano. A continuación muestro los cambios que he realizado:

  • Eliminación de gradientes en el registro seleccionado de las rejillas de datos.
  • Eliminación de efecto de sombra en las pestañas de ordenación de las rejillas de datos.
  • Eliminación de gradientes en los títulos de las listas de acciones.

Además, he dejado de utilizar una clase calendario – lo siento Paco – desarrollada a medida por el control estándar de Windows. El cambio de aspecto se muestra en las siguientes imágenes de mi programa el Puchero, que es el primero que he adaptado al estilo plano.

Y tú, ¿ has adaptado tus programas al diseño plano ?

negresbetanics.com 2.0

En las últimas semanas he estado trabajando en una nueva versión de la web de mi comparsa, Negres Betànics de Novelda. Hice una primera web para la comparsa en el año 2008, pero por varios motivos esta web no se mantuvo y tuve que rehacerla desde cero. La web está hecha con WordPress con los siguientes elementos:

  • Versión free del tema Make
  • Yakanda Instagram, un plugin que permite mostrar imágenes de Instagram de un usuario o que tengan un determinado hashtag. En la web se muestran las imágenes que tienen el hashtag #negresbetanics
  • Cookie law info, un plugin para avisar del uso de cookies en la web.
  • Contact form 7, un plugin para poder incluir un formulario de contacto en la web.

www.negresbetanics.com

En la nueva web hemos querido dar importancia a las filás de la comparsa así como a las capitanías para que los visitantes se puedan hacer una idea de la vistosidad de nuestra fiesta. Muchas de las fotos mostradas en la web son de nuestro comparsista y fotográfo Antonio López.

el año sin pantalones – crítica del libro

Hace unas semanas escribí una entrada sobre el libro El año sin pantalones donde decía que iba a ser una de mis lecturas de verano. Ya he terminado de leerlo y la verdad es que el libro me ha defraudado un poco. Sinceramente esperaba más de este libro. Esta entrada es una opinión personal sobre el libro.

El libro va contando el devenir de un grupo de trabajo de WordPress liderado por Scott Berkun que es el autor del libro. Ese liderazgo queda un tanto difuso, puesto que al tratarse de un grupo de trabajo distribuido fisicamente los problemas que se encuentran son distintos a los de un grupo equipo que trabaja fisicamente junto. La verdad es que apenas cuenta en qué consistió ese liderazgo ni los problemas que encontró ni cómo los resolvió. Sobre el funcionamiento de Automattic cuenta que la empresa funciona mediante grupos de trabajo orientados a funcionalidades de WordPress. Hay unas directrices generales que establece el CEO de la empresa, y luego cada grupo de trabajo es autónomo para desarrollar estas directrices. El funcionamiento de los grupos de trabajo consiste en hacer desarrollos cortos, en ciclos de dos semanas, y liberar rápido. Los principales canales de comunicación dentro de la empresa son el IRC y los P2 que son unos blog donde cualquiera puede publicar. Todas las conversaciones de IRC y entradas de P2 se almacenan y se pueden consultar por cualquier empleado, incluidas las del CEO de la empresa.

Uno de los temas que más me ha gustado es cuando habla de funcionalidades de las aplicaciones y dice que lo importante no es una funcionalidad en si, sino la manera en que esa funcionalidad se diseña para que el usuario la pueda utilizar, y que es una mala idea dejar el diseñó del interfaz una funcionalidad para el final, cuando ya tienes el código hecho. Esto es algo que yo siempre hago en mis programas: antes de programar una nueva funcionalidad tener bien detallado cual va a ser el interfaz de la misma.

El libro tiene pasajes totalmente prescindibles, como todo el episodio del viaje del equipo de trabajo a Grecia. Para mi gusto hay mucho relleno en el libro, de las 250 páginas que tiene el libro se puede contar lo mismo en bastante menos espacio. No es un libro donde se adentre en temas de liderazgo ni de dirección de grupos de trabajo ni de nada, sino que va contando una historia y dando pinceladas de esto y de aquello, pero poco más.

Un libro prescindible desde mi punto de vista, salvo para fanboys de WordPress.

clase TTagEver para FivewinHarbour

Una funcionalidad que quería implementar en el Puchero es la gestión de dietas y tolerancias de las recetas. Es decir que para cada receta se pueda poner si es adecuada para gente con colesterol, celíacos, o para dietas de puntos, Dunkan o lo que sea. Esto supone que cada receta podía llevar asociadas múltiples dietas y la verdad es que no tenía claro cómo hacerlo. Muchas veces lo principal no es la funcionalidad sino como se implementa esta funcionalidad lo que hace que esta sea aceptada por los usuarios o no.

El caso es que dándole vueltas a la cabeza recordé el sistema de etiquetado de documentos que usa Evernote. Algo así:

En FWH hay una clase llamada TTagCloud que podía servirme como base. Esta clase la hizo Francisco García Fernández, que creo que es un gran creador de controles para FWH y además un buen amigo mio. Estuve varias semanas dándole vueltas al control sin conseguir avances significativos, hasta que me puse en contacto con Paco para pedirle ayuda. Paco en un par de días hizo el control, y ahora en el Puchero tengo hecha la implementación de las dietas de esta manera.

Aspecto de la clase TTagEver

La clase desarrollada por Paco está disponible en el siguiente repositorio de GitHub: https://github.com/JoseluisSanchez/TTagEver

Mil gracias Paco.

el año sin pantalones

Portada del libro

Estoy leyendo ‘El año sin pantalones: WordPress.com y el futuro del trabajo‘ de Scott Berkun en la edición en español que ha publicado la editorial Anaya Multimedia. El libro cuenta en primera persona un año de trabajo del autor, Scott Berkun, en Automattic, la empresa desarrolladora del sistema de gestión de contenidos WordPress y propietaria del sitio WordPress.com que aloja este blog.

Reconozco que me gusta este tipo de libros donde se cuenta en primera persona experiencias relacionadas con la gestión de proyectos, y creo que hay pocos libros de estos en español donde la empresa en cuestión sea una empresa de informática. Aunque apenas llevo leida una tercera parte del libro, creo que es un libro recomendable para conocer por dentro el funcionamiento de una empresa de tecnología y la forma en que trabajan. El autor del libro es un conocido escritor sobre gestión de proyectos informáticos, pero Automattic funciona de una manera totalmente distribuida. El contacto entre los trabajadores es virtual a través de IRC, apenas hay correos entre ellos ni tampoco unas directrices claras por parte de la dirección de la empresa. Este es el entorno, o la cultura como dice el autor, en que tiene que desarrollar su trabajo.

El libro tiene mucha parte superflua, no es un libro de gestión de proyectos al uso sino casi más un diario sobre el año de trabajo donde el autor inserta sus reflexiones sobre temas como liderazgo, trabajo en equipo y demás. Creo que es un lujo leer de primera mano como funciona una funciona una empresa como Automattic y la manera en que se organizan los grupos de trabajo dentro de ella.