Monday, 20 July 2009

Creando un editor de propiedades para TBox

La semana pasada os mostré la aplicación Thundax Geometric Links v1.0.0 build 3 donde podíamos ver 2 cajas que se conectaban automáticamente en función de su posición. Pues bien, en la siguiente fase de desarrollo de la aplicación, necesito un editor de propiedades. Cómo lo hacemos?. Pues bien eso es sencillo si tenemos en cuenta las propiedades de Delphi. Aprovecharé la RTTI (Run-time type Information) de delphi, y para ello utilizaré un componente que he utilizado varias veces para estos ejemplos, y es el TcxRTTIInspector de DevExpress. Con este componente, puedo inspeccionar mis clases u objetos pero siempre haciendo que mi clase herede de TPersistent. Si nos fijamos en el código del otro dia, la clase TBox hereda de TObject, pero para que el componente TcxRTTIInspector pueda inspeccionar mis propiedades tengo que hacer una pequeña conversión a TPersistent y luego publicar aquellas propiedades que quiero visualizar. Nos encontraremos con varias dificultades, sobre todo con el tema de visualizar componentes agrupados y enumerados ya que el objetivo del componente es que finalmente visualice clases primarias o básicas (Integer, String). Para hacer juegos con la composición, tendremos que crear diferentes clases y hacer que éstas muestren la agrupación de parámetros que nosotros necesitamos. En mi ejemplo encontraréis los vértices del TBox que los he reconvertido en un TPoints que hereda del TPersistent y que tiene el mismo funcionamiento que el record TPoint.

El inspeccionador de propiedades es el mismo que utilizamos en modo diseño des de cualquier aplicación:

Ahora si realizamos los cambios correspondientes a nuestra clase y la arreglamos, obtendremos lo siguiente:

Éste es mi editor de propiedades para mi TBox, como podéis comprobar es muy sencillo crearlo y más fácil mantenerlo. De esta manera evitamos tener que construir nuestro propio formulario de propiedades y aprovechamos así el RTTI.

El código fuente de la implementación lo tenéis aquí:




type
TDirection = (isUp, isDown, isLeft, isRight);

TPoints = class(TPersistent)
private
Fx: integer;
Fy: integer;
procedure Setx(const Value: integer);
procedure Sety(const Value: integer);
published
property x: integer read Fx write Setx;
property y: integer read Fy write Sety;
public
constructor Create(x: integer; y: integer);
function getPoint(): TPoint;
end;

TBox = class(TPersistent)
private
FColor: TColor;
FSize: integer;
FOffset: integer;
FDirection: TDirection;
FlinkColor: TColor;
Flink: TPoints;
Fcenter: TPoints;
Fvertex: array[0..3] of TPoints;
function getIntersectionPoint(): TPoints;
procedure SetColor(const Value: TColor);
procedure SetOffset(const Value: integer);
procedure SetSize(const Value: integer);
procedure SetDirection(const Value: TDirection);
procedure SetlinkColor(const Value: TColor);
procedure SetcenterPoint(const Value: TPoints);
procedure SetlinkPoint(const Value: TPoints);
procedure Setvertex(Index: integer; value: TPoints);
function Getvertex(Index: integer): TPoints;
procedure SetLink(point: TPoints);
function BetweenX(point: TPoints): boolean;
function BetweenY(point: TPoints): boolean;
procedure SetLinkDirection(up, down, left, right: boolean);
function PointInside(point: TPoints): boolean;
published
property vertex0: TPoints index 0 read Getvertex write Setvertex;
property vertex1: TPoints index 1 read Getvertex write Setvertex;
property vertex2: TPoints index 2 read Getvertex write Setvertex;
property vertex3: TPoints index 3 read Getvertex write Setvertex;
property center: TPoints read Fcenter write SetcenterPoint;
property link: TPoints read Flink write SetlinkPoint;
property Direction: TDirection read FDirection write SetDirection;
property intersection: TPoints read getIntersectionPoint;
property Offset: integer read FOffset write SetOffset;
property Size: integer read FSize write SetSize;
property Color: TColor read FColor write SetColor;
property linkColor: TColor read FlinkColor write SetlinkColor;
public
constructor Create(centerPoint: TPoint; Size, Offset: integer; Color, linkColor: TColor);
end;


implementation

{ TBox }

function TBox.BetweenX(point: TPoints): boolean;
begin

end
;

function TBox.BetweenY(point: TPoints): boolean;
begin

end
;

constructor TBox.Create(centerPoint: TPoint; Size, Offset: integer; Color, linkColor: TColor);
begin
Fcenter := TPoints.Create(centerPoint.x, centerPoint.y);
Fvertex[0] := TPoints.Create(Self.Center.x - Size, Self.Center.y - Size);
Fvertex[1] := TPoints.Create(Self.Center.x + Size, Self.Center.y - Size);
Fvertex[2] := TPoints.Create(Self.Center.x - Size, Self.Center.y + Size);
Fvertex[3] := TPoints.Create(Self.Center.x + Size, Self.Center.y + Size);
Flink := TPoints.Create(0, 0);
FColor := Color;
FlinkColor := LinkColor;
end;

function TBox.getIntersectionPoint: TPoints;
begin

end
;

function TBox.PointInside(point: TPoints): boolean;
begin

end
;

procedure TBox.SetcenterPoint(const Value: TPoints);
begin
Fcenter := Value;
end;

procedure TBox.SetColor(const Value: TColor);
begin
FColor := Value;
end;

procedure TBox.SetDirection(const Value: TDirection);
begin
FDirection := Value;
end;

procedure TBox.SetLink(point: TPoints);
begin

end
;

procedure TBox.SetlinkColor(const Value: TColor);
begin
FlinkColor := Value;
end;

procedure TBox.SetLinkDirection(up, down, left, right: boolean);
begin

end
;

procedure TBox.SetlinkPoint(const Value: TPoints);
begin
Flink := Value;
end;

procedure TBox.SetOffset(const Value: integer);
begin
FOffset := Value;
end;

procedure TBox.SetSize(const Value: integer);
begin
FSize := Value;
end;

function TBox.Getvertex(Index: integer): TPoints;
begin
result := Fvertex[Index];
end;

procedure TBox.Setvertex(Index: integer; value: TPoints);
begin
Fvertex[Index] := Value;
end;

{ TPoints }

constructor TPoints.Create(x, y: integer);
begin
self.fx := x;
self.Fy := y;
end;

function TPoints.getPoint: TPoint;
begin
result := Point(Fx, FY);
end;

procedure TPoints.Setx(const Value: integer);
begin
Fx := Value;
end;

procedure TPoints.Sety(const Value: integer);
begin
Fy := Value;
end;

end.





Para realizar la llamada al RTTI Inspector se hace de la siguiente manera:




procedure TForm1.Button1Click(Sender: TObject);
var
obj: TBox;
begin
obj := TBox.create(Point(10, 10), 8, 5, clBlack, clBlack);
cxRTTIInspector1.InspectedObject := obj;
end;



Espero que os sirva de ayuda.

  • Enlaces de interés:
Delphi property and Component Editor.
Creating Custom components.
Writing a Property Editor.
A Simple Property Editor.

0 comments:

Post a Comment