Showing posts with label Tools. Show all posts
Showing posts with label Tools. Show all posts

Wednesday, 11 August 2010

Nircmd - Freeware Windows command-line tool

Today one of my workmates told me about the Nircmd command-line tool from NirSoft, and I thought it deserved a post in my blog because its strength to modify from turning off your computer to hiding the start button on the system try.
NirCmd is a small command-line utility that allows you to do some useful tasks without displaying any user interface. By running NirCmd with simple command-line option, you can write and delete values and keys in the Registry, write values into INI file, dial to your internet account or connect to a VPN network, restart windows or shut down the computer, create shortcut to a file, change the created/modified date of a file, change your display settings, turn off your monitor, open the door of your CD-ROM drive, and more... 
  You can download the last version of the application from here.

Wednesday, 12 May 2010

Get all environment variables

The other day I had a little incident while I was playing with OpenSSH  (a very interesting tool, and maybe I'll talk about it other day) and most of my environment variables were deleted. To my surprise, despite of all the tools that I have, I didn't have any backup of my environment variables, and this won't happen again!. With a simple application, we can retrieve al the list and save it just in case. I've done this little application "Thundax Get Environment Variables" and with a simple click you can get your list and save it into a file for example.


You can get the source code from here:

Wednesday, 21 October 2009

Worlde

No me he podido resistir a la utilización de Worlde, una herramienta para crear nubes de etiquetas sobre un texto cualquiera. Lo he encontrada mientras leía los feeds del blog, en el blog de José manuel beas. Ésto es lo que he obtenido al introducir mi blog:

La verdad es que es muy bonito y sirve para destacar las diferentes palabras que podemos encontrar en los artículos escritos.

Friday, 16 October 2009

Instalando VLO Framework

Aun estoy ultimando detalles del framework y he integrado éste en el IDE de Delphi. La plataforma consiste en un conjunto de librerías las cuales el usuario final no necesita como funcionan internamente. Simplemente se instala la plataforma de desarrollo en el IDE y se empiezan a utilizar las clases necesarias para el dibujado de los objetos sobre un canvas. Ahora cuando iniciamos el Delphi, podemos ver:

Aun tengo que mejorar el Icono, pero de momento es provisional y meramente informativo para indicar que existe el framework dentro del IDE. El aspecto interno es el siguiente:

Luego una duda que nos puede aparecer es, ¿Cómo puedo hacer para que aparezca el logotipo del package en el Splash screen del Delphi?. Muy fácil, aquí os lo explico:

Una vez tenemos creado nuestro package, tenemos que crear un fichero de recursos que contendrá el logo que queremos que se visualize en el splash del delphi. En mi caso lo he llamado ThundaxVLO.res y he utilizado el XN Resource Editor para crearlo:


Utilizando ésta herramienta gratuita y open source, podemos crear nuestros ficheros de recursos e insertar las imágenes que queramos. Para la conversión de ficheros BMP a ICO he utilizado una aplicación freeware llamada ImageIcon 3.0. Una vez tenemos todos los ficheros necesarios, creamos una nueva unidad en nuestro package que incluirá el procedimiento de registro de los recursos y forzará el incrustado de la imagen en el splash inicial:


unit ThundaxFramework;

interface

{$I JEDI.INC}

procedure Register;

implementation

uses DesignIntf, DesignEditors, Graphics, ToolsAPI;

{$R ThundaxVLO.res}

procedure Register;
{$IFDEF DELPHI10_UP}
var
lBitmap: TBitmap;
Service: IOTAAboutBoxServices;
{$ENDIF}
begin
{$IFDEF DELPHI10_UP}
ForceDemandLoadState(dlDisable);
lBitmap := TBitmap.Create;
try
lBitmap.LoadFromResourceName(hInstance, 'LOGO');
if Assigned(SplashScreenServices) then
SplashScreenServices.AddPluginBitmap('VLO Framework v1.0 ', lBitmap.Handle);
BorlandIDEServices.GetService(IOTAAboutBoxServices, Service);
if Assigned(Service) then
Service.AddPluginInfo('Thundax Software',
'VLO Framework v1.0 ' + sLineBreak + 'Thundax Software', lBitmap.Handle);
finally
lBitmap.Free;
end;
{$ENDIF}
end;

end.


El fichero {$I JEDI.INC} nos interesa para obtener la directiva DELPHI10_UP y saber si estamos ejecutando una versión superior o no, de esta manera se muestra o no el logo en el inicio.

De ésta manera podemos ver también el framework instalado en el About del Delphi:


Espero que os sirva de ayuda!.

Tuesday, 13 October 2009

be more productive!

Uno de los topics que comenta el Pragmatic Thinking and Learning es el tema de aumentar la productividad. Y una de la maneras más rápida de aumentar ésta (hablo de alrededor de un 40% más) es utilizar 2 monitores (Si podemos con más pues mejor!). Hay varios estudios científicos que demuestran éste incremento de la productividad e incluso microsoft hizo el suyo. Si no podemos disponer de 2 monitores una buena solución es utilizar un escritorio virtual y poder disponer de 4 escritorios y cambiar a cada uno de éstos con una simple combinación de teclado.

Aquí os presento una aplicación interesante: VirtualWin una herramienta open source para la virtualización del escritorio (Virtual Desktops). Su instalación y configuración es bastante simple y el único problema que me he encontrado ha sido el de registrar sus hotkeys, que coinciden con mis hotkeys de la tarjeta gráfica. Una vez instalado, veréis en la barra de tareas en la zona de notificación el siguiente icono: el cual nos muestra el escritorio seleccionado. Con las hotkeys configuradas podemos navegar por éste escritorio virtual:

La verdad es que encuentro ésta aplicación muy útil y puedo disponer de varios entornos de trabajo con solo una combinación de teclas (zona de pruebas, redacción de informes, Internet, etc) y me puedo centrar en ése escritorio sin que nada me distraiga. Tengo que destacar el trabajo realizado por Johan Piculell, Steven Phillips y Eric Pierce que han realizado un trabajo increíble.

Friday, 9 October 2009

Thundax Box Manager 2.3

Ya está disponible la versión 2.3 de mi aplicación utilizando mi framework VLO. En ésta versión las novedades son significativas y es que he modificado el tamaño del lienzo. Es decir, ahora podemos navegar por la ventana utilizando unos Scrollbar situados en la horizontal y la vertical del canvas. La manera fácil de implementar ésto es utilizando un TScroBox que permite incrustar una imagen dentro y visualizarla por completo. Pero el problema que se presenta aquí, es que al utilizar mi propio canvas (ThundaxCanvas) éste creará 2 ThundaxScrollBar y gestionarán la vista del lienzo. Lo que he hecho es modificar las coordenadas desde el punto de vista del observador de ésta manera el modelo se entera del cambio y redibuja otra vez toda la imagen posicionandola en la posición correcta. De igual manera podría implementar un zoom (ya lo haré más adelante) pero la estructura es la siguiente:

La visión del observador consiste en mostrar aquella región que es visible desde la aplicación. El lienzo tiene un tamaño de 1280 x 1024 pixels y no se puede mostrar todo por pantalla. Aquí está la razón del tener que implementar éste cambio de perspectiva.

La aplicación ahora tiene el siguiente aspecto:


La última versión no disponía de redimensionado de formulario, y ahora ya está disponible. También he corregido unos cuantos bugs del VLO framework sobre la eliminación de objetos, que no se eliminaban correctamente.


Si probáis de eliminar el nodo 9 en la penúltima versión veréis que aparece una excepción. En ésta última entrega ya no sucede.

Saturday, 3 October 2009

Thundax Box Manager 2.2

Ya está disponible ésta última versión con unas cuantas actualizaciones sobre la selección de proyectos. Aún es un poco básica pero funcional. He creado el siguiente paquete de instalación para la versión 2.2: Thundax Box Manager 2.2. Además trae 3 ejemplos de diagrama para que los cargues y juguéis con ellos.

Al iniciar la aplicación podremos hacer un load de los diagramas guardados:

Aún estoy trabajando en un gestor que me permita manejar mejor todos éstos diagramas, pero de momento dejo ésta versión beta para que la probéis. Los diagramas son altamente portables ya que están guardados en una estructura xml, por lo tanto con coger la carpeta del diagrama que está en la carpeta files\ (la reconoceréis porqué la carpeta acaba en .tbm).

Friday, 2 October 2009

Thundax Box Manager 2.1

Bueno, ya está disponible la última versión de mi aplicación. Ésta "obra de arte" permite ahora las imágenes embebidas de tal manera que podemos superponer sobre la caja una imagen para poder representar aquello que queremos. Estoy muy contento porqué la aplicación va viento en popa y estoy siguiendo al detalle la planificación sobre mi aplicación. Como ya sabréis lo que me habéis seguido a lo largo de éste año y medio, dispongo de mis datos en un CVS y los visualizo utilizando el Redmine. Ésta última herramienta me permite generar nuevas peticiones sobre mi programa y anotar todos los cambios y errores que me voy encontrando para no dejarme nada suelto. Además de mi propia wiki para poder ir subiendo la diferente documentación que voy generando de la aplicación. En ésta versión, la 2.1, encontraréis pocos cambios en lo que a comportamiento se refiere. Las últimas novedades son:
  • Visualización de la lista de Snapshots tomada
  • Corrección de las fugas de memória (Eurekalog)
  • Imagenes embebidas dentro de Tbox
Por lo tanto, ahora podremos hacer diagramas tan espectaculares como el siguiente:


La pantalla de propiedades ha cambiado un poco y ahora nos permite cargar una imagen en formato (.bmp) y hacer la previsualización en el formulario:

De momento la previsualización es de 175 x 75 píxels, lo que provoca que al cargar imágenes con un tamaño más grande se vean cortadas en el visor, pero en la visualización sobre el lienzo no habrá ningún problema.

La aplicación está preparada para poder guardar el diagrama y todos los datos son guardados en la carpeta /resources/images y solo acepta ésta carpeta. Aún queda el tema del guardado de los diagramas que en breve me pondré con ello.

También podéis ver la lista de snapshots que dispone la aplicación:



Podéis descargar la última versión aquí:
NOTA: Si encontráis algún error o Memory leak, por favor, haced un comentario en el blog. gracias.

Thursday, 1 October 2009

Clonezilla : OpenSource clone system (OCS) solution

Quien no ha hecho alguna vez una copia de seguridad de su disco duro? Yo siempre he utilizado el norton ghost (y que yo recuerde desde versiones muy antiguas hasta la última) que para mi gusto funciona bastante bien. Pues bien, hoy os descubro Clonezilla un sistema para hacer copias de seguridad de vuestros discos duros y que además es gratuito. Éste OCS (OpenSource Clone System) dispone de una muy buena solución en formato Live CD la cuál nos permite iniciar nuestro PC con éste Live CD e iniciar una copia de seguridad de nuestros datos más preciados. Podéis descargar la versión estable que he probado clonezilla-live.1.2.2-26.iso en el enlace que os dejo aquí. Es muy parecido a las versiones anteriores de Norton Ghost cuándo tenías que arrancar el PC con el CD y luego se iniciaba un "programilla" para realizar la copia de seguridad. Con Clonezilla funciona de la misma manera, por la web encontraréis manuales completísimos de su funcionamiento y de como realizar una copia de vuestros datos.

  • Enlaces de interés:
Clonezilla - Free Advanced Hard Drive Cloning Software.
Clonezilla live - Clona tu disco o partición de forma gratuita.

Wednesday, 30 September 2009

Primera aplicación con Thundax Box Manager (Parte III)

Ya está disponible la última versión estable de la aplicación Thundax Box Manager que incorpora el framework para el diseño de grafos. En ésta última versión he corregido los siguientes temas:
  • detección de la posición del mouse para evitar colisiones
  • selección múltiple con el SHIFT.
  • Alineación (Top, Bottom, Left and Right) de las cajas seleccionadas.
  • Copiado y pegado de las propiedades
Ahora funciona correctamente todo el tema del dibujado y repintado sin flickering y la verdad que la navegación es bastante buena. Podemos crear diagramas dinámicos como los que siguen a continuación:

En menos de 5 minutos podemos tener grafos totalmente personalizados y lo mejor de todo es que podemos aplicar el algoritmo Dijkstra y obtener el camino mínimo:

Además las pantallas de propiedades han cambiado ligeramente para mostrar más propiedades:

Aquí podréis obtener la última versión de la aplicación y el diagrama:

NOTA: Lo he comprimido con Winrar.

Implementación de un patrón Composite

El patrón composite permite construir objetos complejos a partir de unos más simples. Éste lo he implementado en mi unnamed framework para la copia de propiedades entre objetos. Si os fijáis en la estructura de la plataforma, tanto la Tbox como TLine tienen propiedades muy similares con muy pocas diferencias. Dada la similitud entre éstas he decidido aplicar éste patrón para obtener unas propiedades abstractas las cuáles generan diferentes propiedades para TLine y TBox. De ésta manera puedo construir propiedades más complejas a través de unas más simples. Ésto me permite también separar totalmente de la lógica de control el concepto de propiedad dentro de los objetos. Antes cuando modificaba un objeto lo hacia todo en sí, ahora solo tengo en cuenta las propiedades (y éstas son las importantes). Al objeto caja le tiene que dar igual si le modifican alguna de sus propiedades básicas de dibujo, es el propio objeto propiedad quien se tiene que enterar de éstos cambios y negociarlos con los diferentes objetos.

La nueva estructura de las propiedades es la siguiente:

Ahora tanto la estructura de Tbox como TLine ha quedado reducida a:

Como podéis ver la gestión de las conexiones la he migrado a una unidad nueva ya que es mejor tenerlo todo separado.

Con la solución propuesta anteriormente, ahora podemos hacer ésto desde el lienzo personalizado:

Ésto nos permite copiar las propiedades de nuestros objetos utilizando la TAbstractProperty, de ésta manera la podemos pasar a cualquier objeto ya que todas las propiedades heredan de ésta clase.

Si nos fijamos en la siguiente imagen veréis que tanto la primera caja como la línea tiene asignada la misma propiedad:

En enlace de la aplicación es el siguiente:
NOTA: La aplicación ha cambiado substancialmente y el intentar cargar un diagrama anterior a ésta versión puede que acabe en error. Aún tengo que gestionar todo el tema de los ficheros y su almacenado.


Tuesday, 29 September 2009

Primera aplicación con Thundax Box Manager (Parte II)

Aquí os dejo la última versión de Thundax Box Manager que incluye el algoritmo Dijkstra para la búsqueda del camino más corto (versión mejorada). Ahora el algoritmo funciona correctamente y permite generar grafos de hasta 100 vértices (realmente podríamos poner los que quisiéramos). En las siguientes imágenes podréis ver como se busca el camino más corto marcando un vértice inicial y uno final. Si os fijáis el código no es muy extenso y es de fácil comprensión (tampoco he tardado mucho en sacarlo, la idea y su funcionamiento los tenía muy claro). Ahora simplemente es cuestión de tiempo el empezar a automatizar ideas y empezar a dibujar cosas pre-tratadas para hacer más amena la inserción de bloques en el lienzo. También tengo pensado mejorar la capacidad de copiar y pegar propiedades, ya que he notado que la edición es bastante lenta y hay que mejorar eso. También el clonado de objetos debería ser más fácil y desde el teclado poder hacer alguna cosa. Cada vez que manejo la herramienta me voy dando cuenta de las cosas que aún le faltan y es que aún está bastante verde, pero por lo menos hay una buena base, bien estructurada con una buena implementación hacia la Orientación a Objetos, Persistencia de datos y un buen uso de los patrones de diseño.


Aquí os dejo los enlaces para la descarga de la aplicación que además incorpora el diagrama. Tan solo tenéis que dejar el diagrama en la carpeta donde esté el ejecutable y hacer un load. Luego os aparecerá el mismo diagrama que veis aquí.

El código fuente del algoritmo para la resolución del camino más corto utilizando DijKstra es el siguiente:


procedure TfrmMain.Dijkstra1Click(Sender: TObject);
const
NoWeight = 999999;
MaxVertexs = 12;
type
ArrayOfInteger = array[1..MaxVertexs] of Integer;
var
AdjacentList: array[1..MaxVertexs, 1..MaxVertexs] of Integer;
VertexList: ArrayOfInteger;
predecessor: ArrayOfInteger;
visiteds: array[1..MaxVertexs] of boolean;
vertexs, edges, firstNode, LastNode: integer;
i, j, pos1, pos2, min: integer;
Conn: TConnector;
textList: string;
DrawingList : ArrayOfInteger;
begin
vertexs := boxlist.count;
edges := connectorList.count;
firstNode := -1;
LastNode := -1;
for i := 0 to BoxList.count - 1 do
begin
if BoxList.items[i].boxColor = clLime then
firstNode := StrToInt(BoxList.items[i].getText);
if BoxList.items[i].boxColor = clFuchsia then
LastNode := StrToInt(BoxList.items[i].getText);
end;
if (firstNode = -1) or (LastNode = -1) then
exit;

RestoreDefaults1Click(Sender);

for i := 1 to MaxVertexs do
begin
for j := 1 to MaxVertexs do
begin
AdjacentList[i, j] := NoWeight;
if i = j then
AdjacentList[i, j] := 0
end;
DrawingList[i] := NoWeight;
end;

for i := 0 to edges - 1 do
begin
Conn := ConnectorList.items[i];
pos1 := StrToInt(Conn.SourceBox.GetText);
pos2 := StrToInt(Conn.targetBox.GetText);
AdjacentList[pos1, pos2] := StrToInt(Conn.Line.GetText);
if Conn.Line.ClassNameIs('TAbstractDottedDoubleArrowLine') or
Conn.Line.ClassNameIs('TAbstractSimpleDoubleArrowLine') then
AdjacentList[pos2, pos1] := StrToInt(Conn.Line.GetText);
end;

for i := 1 to vertexs do
begin
VertexList[i] := AdjacentList[firstNode, i];
predecessor[i] := firstNode;
visiteds[i] := false;
end;
VertexList[firstNode] := 0;
visiteds[firstNode] := true;

j := firstNode;
repeat
for i := 1 to vertexs do
if (not visiteds[i]) and (VertexList[i] > VertexList[j] + AdjacentList[j, i]) then
begin
VertexList[i] := VertexList[j] + AdjacentList[j, i];
predecessor[i] := j;
end;
min := NoWeight;
for i := 1 to vertexs do
if (not visiteds[i]) and (VertexList[i] < min) then
begin
min := VertexList[i];
j := i;
end;
if (min <> NoWeight) then
visiteds[j] := true;
until (visiteds[LastNode]) or (min = NoWeight);

textList := '';
DrawingList[firstNode] := LastNode;
j := firstNode;
while (LastNode <> firstNode) do
begin
j := j + 1;
LastNode := predecessor[LastNode];
DrawingList[j] := LastNode;
end;

i := 1;
while i < length(DrawingList) do
begin
for j := 0 to connectorList.count - 1 do
begin
Conn := ConnectorList.items[j];
if ((Conn.SourceBox.getText = IntToStr(DrawingList[i])) and
(Conn.TargetBox.getText = IntToStr(DrawingList[i+1]))) or
((Conn.SourceBox.getText = IntToStr(DrawingList[i+1])) and
(Conn.TargetBox.getText = IntToStr(DrawingList[i]))) then
begin
Conn.SourceBox.lineColor := clRed;
Conn.TargetBox.lineColor := clRed;
Conn.Line.LineColor := clRed;
end;
end;
i := i + 1;
end;
end;


En definitiva, creo que la aplicación va por buen camino y estoy contento porque por fin tengo una aplicación visual para poder tratar los diferentes datos que tengo en mente. Ya os iré contando!.


Mejorando el diseño de una flecha (Parte II)

He detectado un pequeño error en la composición de la flecha. Cuándo el ángulo representado es igual a pi/2 o -pi/2 la flecha no se dibuja correctamente, solo aparece la punta sin el relleno, es decir, el polígono no se dibuja correctamente. La solución (como siempre) es bastante fácil y solo hay que tener en cuenta la distribución geométrica de los puntos de representación de la punta de flecha. El problema reside en la comparación utilizando reales. Éstos no se pueden comparar realmente, ya que siempre son diferentes internamente, por lo tanto cuando el programa intenta comparar los valores de pi/2 con el valor calculado de pi/2 dice que no son iguales:

La funcion consiste en mirar si el valor absoluto del angulo difiere de un ángulo de pi/2, y si realizamos la comparación con el debugger no dirá que los valores no son iguales, y visualmente lo son.

Para evitar ésto utilizaré una función que os mostré hace tiempo en uno de mis posts para la comparación de reales: Comparando reales con delphi.

Mediante éste último arreglo, el framework (aún estoy pensando en que nombre darle, pero al final caerá algo como TWAIN Technology without an Interesting Name) tiene bastante resuelto todo el tema del cálculo para el repintado de las diferentes estructuras.

El código final del dibujado de la flecha es el siguiente:


procedure TAbstractLine.DrawFashionArrow(Source, Target: TPoint);
function CalcPoint(p: TPoint; angle: double; Distance: integer): TPoint;
var
X, Y, M: double;
begin
if Comparar(Abs(angle),(PI / 2),'<>') then
begin
if Comparar(Abs(angle),(PI / 2),'<') then
Distance := -Distance;
M := Tan(angle);
X := p.X + Distance / sqrt(1 + sqr(M));
Y := p.Y + M * (X - p.X);
Result := Point(round(X), round(Y));
end
else
begin
if angle > 0 then
Distance := -Distance;
Result := Point(p.X, p.Y + Distance);
end;
end;

var
angle: double;
PArrow: array[1..4] of TPoint;
restColor: TColor;
begin
if (Distance(Source, Target) < 20.0) or (Distance(Source, Target) > 2000.0) then
exit;
angle := ArcTan2((Target.Y - Source.Y), (Target.X - Source.X));
PArrow[1] := Target;
PArrow[2] := CalcPoint(Target, angle + PI / 9, LenArrow);
PArrow[3] := CalcPoint(Target, angle, 2 * LenArrow div 3);
PArrow[4] := CalcPoint(Target, angle - PI / 9, LenArrow);
FCanvas.Pen.Width := 1;
if FInside then
FCanvas.Pen.Color := FSelectedColor
else
FCanvas.Pen.Color := FLineColor;
FCanvas.Brush.Style := bsSolid;
restColor := FCanvas.Brush.Color;
if Ffilled then
FCanvas.Brush.Color := FFillColor;
FCanvas.Polygon(PArrow);
FCanvas.Brush.Color := restColor;
end;


La actualización de la función de comparación también la dejo ya que faltaba un operador de comparación:


uses types, Math;

function Comparar(Value1, Value2: double; MethodComp: string): boolean;

const
RealMargin = 0.000001; //1e-6

implementation

function Comparar(Value1, Value2: double; MethodComp: string): boolean;
var
ret: boolean;
begin
ret := false;
if MethodComp = '=' then
begin
case CompareValue(Value1, Value2, RealMargin) of
EqualsValue: ret := true;
end;
end
else if MethodComp = '<>' then
begin
case CompareValue(Value1, Value2, RealMargin) of
LessThanValue: ret := true;
GreaterThanValue: ret := true;
end;
end
else if MethodComp = '>=' then
begin
case CompareValue(Value1, Value2, RealMargin) of
EqualsValue: ret := true;
GreaterThanValue: ret := true;
end;
end
else if MethodComp = '>' then
begin
case CompareValue(Value1, Value2, RealMargin) of
GreaterThanValue: ret := true;
end;
end
else if MethodComp = '<=' then
begin
case CompareValue(Value1, Value2, RealMargin) of
LessThanValue: ret := true;
EqualsValue: ret := true;
end;
end
else if MethodComp = '<' then
begin
case CompareValue(Value1, Value2, RealMargin) of
LessThanValue: ret := true;
end;
end;
result := ret;
end;


Ahora, el dibujado de las flechas es perfecto:

Espero que os sirva de ayuda.

Monday, 28 September 2009

Thundax Box Manager 2.0

Ya está disponible la última versión de la aplicación Thundax Box Manager 2.0, la cuál ajustando unos cuantos conceptos de diseño pasará a convertirse en un framework de trabajo para poder dibujar objetos sobre un canvas. En ésta versión he acabado de implementar la persistencia de objetos mediante Marshal y Unmarshal con apoyo mediante XML. Aunque trae bastante trabajo, es fácil de implementar y fácil de seguir sin tocar el diseño original de nuestras clases. Entre las últimas novedades que utiliza la herramienta puedo destacar:
  • Identificador único de objeto utilizando un GUID.
  • Persistencia del lienzo mediante una estructura simple en XML.
  • Tamaño del lienzo modificado a 1024 x 780 pixels.
Si analizamos el nuevo diseño de las clases podemos ver:

La famosa clase TBox, que implementa las interfaces ISerializable y ICloneable, permitiendo así que el objeto pueda ser clonado y serializado para su posterior almacenaje o persistencia.


Otra de las partes más importantes de la aplicación es la generación de las líneas y su cálculo. La factoría abstracta ha sido modificada levemente para poder realizar una llamada a un elemento de la factoría a través de su nombre.


TAbstractFactory = class(TObject)
private
FCanvas: TCanvas;
public
constructor Create(Canvas: TCanvas);
destructor Destroy; override;
function GetLine(): TAbstractLine; virtual; abstract;
function GetLineArrow(): TAbstractLine; virtual; abstract;
function GetLineDoubleArrow(): TAbstractLine; virtual; abstract;
function GetLineByName(name : String) : TAbstractLine; virtual; abstract;
end;


Entre los otros aspectos a destacar tenemos las diferentes implementaciones de:

TVertex es una clase mucho más compleja que el registro TPoint (éste último lo he tenido que eliminar por problemas de serialización con Delphi 2010). De ésta manera puedo tener control sobre los vértices y añadirles más propiedades y eventos a éstos.

Luego dispongo de las interfaces que me permiten implementar la clonación y serialización en mis clases básicas Tbox y TAbstractLine.

En las siguientes imágenes muestro las posibilidades que tiene la aplicación para poder crear diversos grafos conectados:


Si nos fijamos en las pantallas de propiedades, veremos que cada objeto está identificado con su identificador único GUID, el cuál aparece representado en el lateral de la pantalla de propiedades:

El tema de la generación del GUID con delphi es muy simple. Si lo queremos para nuestras interfaces, solo tenemos que pulsar CTRL+SHIFT+G '{F6676376-D14B-4860-AD5B-D920DF25E52D}' y obtendremos uno nuevo. Para hacer la llamada mediante una función o método, solo tenemos que utilizar la siguiente función:


uses
ComObj, ActiveX;

function CreateGuid(): string;

implementation

function CreateGuid(): string;
var
ID: TGUID;
begin
Result := '';
if CoCreateGuid(ID) = S_OK then
Result := GUIDToString(ID);
end;


Ahora los siguientes pasos consisten en utilizar ésta base desarrollada y generar aplicaciones más potentes con componente visual. Si os fijáis en la declaración de las clases, de momento he dejado un puntero personalizable en cada objeto TBox y TAbstractLine para que le podamos dar la utilización que queramos.

Gráficamente disponemos de lo siguiente:

Podemos utilizar cada uno de los objetos y colgar nuestro objeto personalizado. De ésta manera, la parte gráfica queda solucionada por TBox y la lógica la podemos hacer externa. En los próximos posts intentaré implementar alguna herramienta típica con mi framework a ver que sale.

En definitiva, el entorno es casi funcional y permite crear bonitos grafos conectados. He podido arreglar temas de aliasing, temas de intersección de rectas y trabajar con puntos en el espacio. Como veis no es tan trivial crear algo que dibuje objetos sobre un lienzo. Hay que disponer de "culturilla" general para poder realizar correctamente los cálculos matemáticos y saberlos transformar para que el ordenador los entienda. Como digo yo, realizar una integral a mano es relativamente fácil, ahora lo complicado es hacerlo para que el ordenador sea capaz de hacerla. Siempre me han fascinado las partes gráficas de los IDE's o de aplicaciones, y creo que es una parte bastante complicada de implementar.



Friday, 25 September 2009

Syntax helper

En éste artículo os muestro una pequeña aplicación que hice para automatizar la conversión del código Delphi a HTML para utilizar la herramienta de Syntax Highlighter de Alex Gorbatchev. Con ésta herramienta podremos pasar el código que vamos a colgar en el blog al formato requerido para ésta fabulosa herramienta. Además he incrustado un visor para hacer la previsualización de cómo quedará el código una vez hagamos los cambios. Podéis descargaros aquí la última versión estable de mi aplicación ThundaxSyntaxHelper la cuál permite automatizar un poco más rápido la subida del código a nuestros blogs.

Luego si nos vamos a la pestaña de previsualización, nos aparece el resultado de formatear nuestro código:

Espero que os sirva de ayuda.

Aquí os dejo el código que se mostrará utilizando el Syntax Highlighter de Alex Gorbatchev:


procedure TForm3.GetText1Click(Sender: TObject);
var
i : integer;
text : string;
begin
memo2.Lines.Clear;
memo2.lines.add('<pre class="brush: delphi">');
for i := 0 to memo1.lines.count-1 do
begin
text := AnsiReplaceStr(memo1.lines[i],'<', '<');
text := AnsiReplaceStr(text,'>', '>');
memo2.lines.Add(text);
end;
memo2.lines.add('</pre>');
end;

procedure TForm3.AddFile(s: string);
var
LogFile: TextFile;
begin
AssignFile(LogFile, ExtractFilePath(ParamStr(0)) + 'test.html');
try
if FileExists(ExtractFilePath(ParamStr(0)) + 'test.html') then
Append(LogFile)
else
Rewrite(Logfile);
WRITELN(LogFile, s);
CloseFile(LogFile);
except
end;
end;

procedure TForm3.Preview1Click(Sender: TObject);
var
i : integer;
text : string;
begin
if fileExists(ExtractFilePath(ParamStr(0)) + 'test.html') then
DeleteFile(ExtractFilePath(ParamStr(0)) + 'test.html');

for i := 0 to memo3.Lines.count-1 do
begin
AddFile(Memo3.lines[i]);
end;
for i := 0 to memo2.Lines.count-1 do
begin
AddFile(Memo2.lines[i]);
end;
AddFile('</html>');
text := ExtractFilePath(ParamStr(0)) + 'test.html';
text := AnsiReplaceStr(text,'\','/');
WebBrowser1.Navigate('file:///' + text);
end;


  • Enlaces de interés:
Integrando un syntax Highlighter para el código del blog.

Thursday, 24 September 2009

Corrigiendo el aliasing del texto inclinado

Prosiguiendo los cálculos realizados sobre mi aplicación Thundax Box Manager, en éste artículo daré importancia a la corrección del Aliasing que ocurre en el momento de inclinar el texto. La propia API de windows nos permite trabajar con las fuentes modificando los parámetros básicos de éstas y definiendo así su calidad. Si observamos la siguiente imagen sacada de la aplicación, notaréis como el sistema intenta dibujar las letras orientadas con una inclinación de la manera que puede. La verdad es que no se entienden muy bien y no queda muy bonito en la aplicación.

Si consultamos los parámetros de CreateFont, podemos ver que trabaja bastante bien con fuentes Truetype y que además permite corregir el aliasing ajustando un parámetro de su función. Mediante el parámetro fdwQuality [in]:
The output quality. The output quality defines how carefully GDI must attempt to match the logical-font attributes to those of an actual physical font. It can be one of the following values.
Podemos utilizar el valor: ANTIALIASED_QUALITY.
Font is antialiased, or smoothed, if the font supports it and the size of the font is not too small or too large.
Aquí podéis ver las diferentes pruebas realizadas cambiando el tipo de fuente y el tamaño:


Como podéis ver mediante el valor seleccionado podemos mejorar el aliasing de la fuente aplicando un filtro antialiasing sobre el texto rotado. Desde la aplicación, podemos ir probando las diferentes fuentes que tenemos instaladas pero he comprobado que hay muchas fuentes que no disponen de éste comportamiento. Al principio había dejado por defecto la fuente Tahoma, pero no funciona tan bien como la Calibri que es la que utiliza Microsoft Office. Ahora en la aplicación, las fuentes tienen mejor aspecto:


Para acabar de mejorar el método de pintado del texto, he arreglado un tema pendiente sobre centrar el texto en la línea. El cálculo es como siempre bastante fácil y solo tenemos que recurrir a la trigonometría para solucionar ésto.

El problema reside en que el texto empieza a dibujarse desde el centro de la línea, ya que se calcula el punto médio entre el origen y el final de la conexión. Pero claro, tenemos que tener en cuenta la longitud del texto escrito y desplazar el centro la mitad de ésta longitud para que el texto se muestre centrado:

En la siguiente imagen describo el cálculo con un poco más de precisión:

Utilizando la función Canvas.TextWidth podemos saber la longitud actual del texto en píxels, luego solo necesitamos dividir éste valor entre 2 para obtener la mitad de la longitud. Ahora sabiendo el ángulo de inclinación tenemos que calcular los valores de a y b para calcular el nuevo punto a partir de P.

La nueva función del cálculo de la orientación queda de la siguiente manera:


procedure TAbstractLine.DrawTextOrientation(Source, Target: TPoint);

function iif(condition: boolean; resultTrue: integer; resultFalse: integer): integer;
begin
Result := resultFalse;
if condition then
Result := resultTrue
end;

var
newFont, FontSelected: integer;
angle: double;
iAngle, i: integer;
Position: TPoint;
calc : double;
begin
if FDescription.text = '' then
exit;
angle := CalcAngleTwoPoints(Source, Target);
iAngle := round(angle);

if (iAngle >= 91) and (iAngle <= 180) then
iAngle := iAngle + 180;

if (iAngle >= 181) and (iAngle <= 269) then
iAngle := iAngle - 180;

for i := 0 to FDescription.Count - 1 do
begin
Position := Point((Target.X + Source.X) div 2, (Target.Y + Source.Y) div 2);
FCanvas.Font := FFontText;
calc := (FCanvas.TextWidth(FDescription[i]) div 2) * cos(DegToRad(iAngle));
Position.x := Position.x - round(calc);
calc := (FCanvas.TextWidth(FDescription[i]) div 2) * sin(DegToRad(iAngle));
Position.y := Position.y + round(calc);

SetBkMode(FCanvas.Handle, transparent);
newFont := CreateFont(-FfontText.Size, 0, iAngle * 10, 0, iif(fsBold in FfontText.Style, FW_BOLD, FW_NORMAL), iif(fsItalic in FfontText.Style, 1, 0), iif(fsUnderline in FfontText.Style, 1, 0), iif
(fsStrikeOut in FfontText.Style, 1, 0), ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, PChar(FfontText.Name));

Fcanvas.font.color := FfontText.color;
FontSelected := SelectObject(FCanvas.Handle, newFont);
TextOut(FCanvas.Handle, Position.X , Position.Y, PChar(FDescription[i]), Length(FDescription[i]));
SelectObject(FCanvas.Handle, FontSelected);
DeleteObject(newFont);
end;
end;


La última versión de la aplicación con éstos cambios la podéis encontrar aquí: Thundax Box Manager v1.0.0 build 159.exe.

Aquí os dejo con una imagen de la aplicación utilizando el corrector de aliasing:


  • Enlaces de interés:
Display rotated text.
Image Processing.
Graphic Algorithms.
Flicker Free TImage Delphi.
Win32 and COM Development.
Delphi DegToRad Command.