27 enero 2006

Variables de menos de un byte en C

En C es posible crear una estructura cuyos campos tengan menos de 1 byte de tamaño. Esto es útil, por ejemplo, si queremos muchos booleanos.

Cuando tenemos booleanos, lo normal es hacer un entero de valor 0 o 1. Si somos listos, quizás pongamos un char que ocupa menos.

Con algo como esto, podemos hacer una estructura con muchos booleanos dentro de un solo bit. La siguiente estructura, por ejemplo, contiene 5 booleanos de 1 bit.

struct Booleanos
{
unsigned int b1:1;
unsigned int b2:1;
unsigned int b3:1;
unsigned int b4:1;
unsigned int b5:1;
}


Posiblemente el compilador haga que la estructura completa ocupe uno o varios bytes completos (según la cantidad de campos que metamos dentro), pero hemos conseguido un ahorro importante de espacio de memoria.

Tambien es posible hacer campos de dos bits, de tres, etc.

struct VariableRaras
{
unsigned int a:3; /* 3 bits */
unsigned int b:4; /* 4 bits */
}


En estos campos sólo caben número pequeños. Por ejemplo, en a sólo podemos meter números de 0 (000 en binario) a 7 (111 en binario). Si nos pasamos de rango, estaremos machacando el campo anterior o el siguiente (depende del micro que usemos).

En fin, esto es útil para ahorrar espacio de memoria o incluso cuando trabajamos a nivel de bits, para acceder más fácilemte a bits o grupos de bits dentro de una zona de memoria.

En http://www.zator.com/Cpp/E4_6.htm hay un tutorial más completo sobre esto

26 enero 2006

Aplicaciones para windows y linux

En http://es.wikipedia.org/wiki/Equivalencias_Windows_en_Linux#Programaci.C3.B3n_y_Desarrollo hay una lista de aplicaciones para windows y linux.

Teóricamente hace una especie de relación entre una y otra, de forma que si conocemos una herramienta para windows, seamos capaces de ver qué herramientas similares hay en linux.

Aunque no estoy del todo de acuerdo con todas las equivalencias que muestra (hay herramientas que corren en ambos sistemas por ser java y sólo aparecen en uno), el enlace es interesante para conocer herramientas existentes. Hay aplicaciones de autocad, para manejo de cvs, IDEs de trabajo, compiladores para varios lenguajes, sistemas de informacion georeferenciada (mapas), etc.

25 enero 2006

Llamar a otros ant desde un ant

Desde un build.xml de ant podemos hacer llamadas a otros build.xml ejecutándose en un ant aparte. También podemos llamar a otros "target" del mismo build.xml

Para llamar a otro "target" que esté en el mismo build.xml, hacemos algo como esto

<target name="llamar_a_otro_target">
<antcall target="otro_target"/>
</target>


<target name="otro_target">
<!-- Aqui se hacen cosas-->
</target>


Para llamar a otro "target" que esté en otro build.xml, se hace así

<target name="llamar_a_otro_target_de_otro_build">
<ant antfile="/directorio/build.xml"
dir="/directorio"
target="otro_target"/>
</target>


Si no ponemos "target" en la llamada a ant, se ejecutará el "target" por defecto del build.xml

24 enero 2006

Ficheros de propiedades en ant

Hay una pequeña tontería de ant que he descubierto hace poco y me ha llamado la atención.

Consiste básicamente en que podemos poner en un fichero (que suelo llamar build.properties) una serie de propiedades al estilo de fichero de propiedades java, es decir, algo como esto

variable1=valor1
variable2=valor2

Luego, en ant, justo debajo del tag de project, podemos hacer que se lea este fichero de propiedades

<project basedir="." default="all" name="MiProyecto">
<property file="build.properties"/>
...
</project>

Con esto se leen las variables del fichero de propiedades y luego pueden usarse fácilmente en las tareas que tengamos definidas en el build.xml. Por ejemplo

<javac srcdir="${FUENTES}" destdir="${DIRECTORIO_CLASS}" ...>
...
</javac>

compilaría en java lo que encuentre en el directorio al que apunte la variable/propiedad FUENTES y dejaría los ficheros .class en el directorio al que apunte la variable/propiedad DIRECTORIO_CLASS.

23 enero 2006

Cuando me meten en una ventana

Con relativa frecuencia hago clases que heredan de JButton, por ejemplo, MiBoton. Esta clase MiBoton ya tiene implementado el código que debe ejecutarse al apretar el botón y es un código más o menos reutilizable en varios sitios (por eso el hacer el botón en concreto).

A veces ese botón necesita abrir una pequeña ventana secundaria (una ventana de confirmación, para introducir algunos datos o lo que sea). Esa ventana, para que todo cuadre como debe ser, debe ser un JDialog cuyo padre sea la ventana (JFrame o JDialog) que contiene al botón, de esta forma el dialogo que abramos no saldrá detrás de la ventana que contiene al botón. Y ahí viene el problema. Cuando se hace el código del botón más o menos genérico, no se dispone de la ventana que contiene el botón. De hecho, si el botón está en una especie de librería, no se sabe quién lo va a utilizar ni en qué ventana lo va a poner.

La solución que le he dado a este problema, es crear un HierarchyListener. El botón se suscribe a un cambio en la jerarquía de padres de él mismo. De esta forma, cuando el botón se añade a un panel o ese panel se añade a una ventana, el botón se entera. Con cada cambio de jerarquía, se intenta obtener la ventana padre del botón, utilizando el método SwingUtilities.getWindowAncestor(). En el momento que este método nos devuelva una ventana, esta será la ventana que contiene al botón y esta será la ventana padre del JDialog que va a desplegar el botón.

El código para todo esto puede estar en el constructor de MiBoton y es algo como esto

this.addHierarchyListener(new HierarchyListener( )
{
public void hierarchyChanged( HierarchyEvent e )
{
// Se mira si el panel ya ha sido añadido a alguna ventana
Component ventana = SwingUtilities.getWindowAncestor( EditorListaStrings.this );

if( ventana != null )
{
// Se elimna la suscripción para evitar construir la
// ventana dos veces
EditorListaStrings.this.removeHierarchyListener( this );
// Construye el dialogo usando como padre ventana
construyeDialogo (ventana);
}
}

} );

19 enero 2006

Enterarnos de que nuestro programa java termina

Tenemos la posibilidad de enterarnos de que nuestro programa java termina, bien por hacer System.exit(), bien por la pulsación de Ctrl-C. De esta forma, al producirse la salida, podemos realizar ciertas tareas antes de que termine la ejecución.

La forma es utilizar el método addShutdownHook() de la clase Runtime. A este método le pasamos un Thread que se arrancará cuando se produzca el exit() o la terminación por Ctrl-C.

El siguiente trocito de código hará que se escriba "Adios" al terminarse nuestro programa

Thread hilo = new Thread (new Runnable ()
{
public void run ()
{
System.out.println ("Adios");
}
});

Runtime.getRuntime().addShutdownHook(hilo);

Lo de que queramos enterarnos cuando se pulsa Ctrl-C es entendible. ¿Para qué sirve enterarnos de un exit(), si lo hacemos nosotros?. Tiene bastante sentido en clases que formen parte de una librería más o menos reutilizable. Si hacemos una clase común/reutilizable que necesite hacer algo cuando termina el programa, ya no dependemos de que el que la use nos llame a algún método antes de hacer exit(). Nuestra propia clase puede usar este sistema para asegurarse de ser llamada al terminar el programa java.

17 enero 2006

Patrón fachada

Supongamos que tenemos una librería gráfica similar a la que tengo en mi página.

En ella hay una clase Lienzo que es la zona de dibujo para dibujar. Hay una clase EscalaGrafica que es la encargada de hacer las conversiones de coordenadas deseadas para el gráfico a coordenadas de pixels de pantalla y viceversa. Esta clase se encarga, por ejemplo, de hacer las cuentas para que un Lienzo con 100 pixels de ancho tenga unos valores de x que van de -PI a +PI para dibujar una función sin(x). También hay una clase Rejilla para dibujar unos ejes y un cuadriculado. Hay una clase Mano para permitir arrastrar con el ratón un gráfico. Hay unas clases de botonería de zoom para poder hacer zoom en el gráfico. También hay unas clases Cursor que al pasear el ratón por encima del gráfico nos van diciendo las coordenadas del gráfico en las que estamos, aparte de permitir dejar unas marcas en el gráfico.

Ahora supongamos que vamos a hacer un programa matemático en el que tenemos una interface de usuario y en ella hay unos 200 gráficos. Todos ellos son de funciones matemáticas y queremos que tengan un aspecto similar. Todos pintarán una función matemática, llevarán una rejilla, unos botones de zoom y una mano que permita arrastrar el gráfico.

Para hacer cada uno de estos gráficos debemos hacer los siguientes pasos:
  • Instanciar la clase Lienzo.
  • Instanciar la clase EscalaGrafica que convierte coordenadas a pixels y meterla en la clase Lienzo.
  • Instanciar la clase Rejilla y meterla en Lienzo.
  • Instanciar la clase Mano y meterla en Lienzo.
  • Instanciar los botones de zoom, pasarles la EscalaGrafica y ponerlos en un contenedor junto al Lienzo.
  • Finalmente, el paso que es especifico de cada grafico, que es instanciar el ObjetoGrafico que representa la funcion matemática que queremos pintar y meterlo en el Lienzo.
Vemos que hay un montón de pasos que son comunes a todos los gráficos. Son comunes todos excepto el último, en el que la función será la que sea. También vemos que hay un pequeño berenjenal de clases e inicializaciones entre ellas.

El patrón fachada nos dice que podemos hacer una clase que nos oculte toda esta complejidad. La clase puede ser GraficoDeFuncion, que sea un contenedor (un JPanel java) que dentro instancie el Lienzo, la botonería de Zoom, la Mano, la EscalaGrafica y la Rejilla. Lo inicialice y lo coloque todo en su sitio. Únicamente habría que pasarle desde fuera la función matemática que queramos y si acaso los valores extremos de coordenadas (de -PI a PI para x y de -1 a 1 para y si queremos pintar un sin(x), por ejemplo).

De esta forma, en nuestra aplicación, iremos instanciando clases GraficoDeFuncion que son más fáciles de inicilizar.

En resumen, el patrón fachada consiste en crear una única clase de manejo más fácil que nos permita acceder a un conjunto más o menos numeroso y complicado de clases que necesitan una inicialización compleja. Quizás no nos deja hacer todo lo que se podría hacer con las clases sueltas (por ejemplo, no poner Mano a un gráfico o ponerle una botonería de zoom distinta a las demás), pero nos ahorra mucho el trabajo de instanciación e inicialización de todo eso.

15 enero 2006

iText : Una librería para pdf en java

iText es una librería gratuita que permite generar ficheros pdf desde código java. No la he probado, pero es una cosa a mirar si alguna vez hace falta...