{ TOrtoLink }
TOrtoLink = class(TGraphLink)
private
UltPunto : integer; // cantida de puntos en uso del siguiente array
Puntos: array [0..5] of TPoint; ///
protected
procedure DrawMarkers(Canvas: TCanvas); override;
procedure DrawBody(Canvas: TCanvas); override;
procedure CalculateEndPoints;override;
function GetTextRegion: HRGN; virtual;
public
constructor Create(AOwner: TSimpleGraph); override;
function ContainsPoint(X, Y: Integer): Boolean; override;
end;
{TOrtoLink}
constructor TOrtoLink.Create(AOwner: TSimpleGraph);
begin
inherited Create(AOwner);
UltPunto := 2;
Text := 'Orto';
setKind(lkDirected);
end;
function TOrtoLink.ContainsPoint(X, Y: Integer): Boolean;
var
Margin,i: Integer;
R: TRect;
begin
Result := False;
if Showing and (FromNode <> nil) and (ToNode <> nil) then /////
begin
if (TextRegion <> 0) and PtInRegion(TextRegion, X, Y) then
Result := True
else
begin
Margin := Pen.Width + Owner.MarkerSize;
if DistanceToLine(StartPt, EndPt, Point(X, Y)) <= Margin then
begin
Margin := Margin div 2;
R := MakeRect(StartPt, EndPt);
InflateRect(R, Margin, Margin);
Result := PtInRect(R, Point(X, Y));
exit;
end;
for i := 0 to UltPunto -1 do
begin
if DistanceToLine(Puntos[i], Puntos[i+1], Point(X, Y)) <= Margin then
begin
Margin := Margin div 2;
R := MakeRect(Puntos[i], Puntos[i+1]);
InflateRect(R, Margin, Margin);
Result := PtInRect(R, Point(X, Y));
exit;
end;
end;
end;
end;
end;
procedure TOrtoLink.DrawMarkers(Canvas: TCanvas);
var
rect : Trect;
i : byte ;
begin
///
if not Dragging and IsVisibleOn(Canvas) then
begin
Canvas.Brush.Color := Owner.MarkerColor;
Canvas.Brush.Style := bsSolid;
//Canvas.FillRect(MarkerRect(mtMoveStrartPt));
//Canvas.FillRect(MarkerRect(mtMoveEndPt));
if (FromNode <> nil) and (ToNode <> nil) then
begin
for i := 0 to UltPunto do
begin
SetRect(Rect, Puntos[i].X, Puntos[i].Y, Puntos[i].X, Puntos[i].Y);
InflateRect(Rect, Owner.MarkerSize, Owner.MarkerSize);
Canvas.FillRect(rect);
end;
end;
end;
end;
procedure TOrtoLink.DrawBody(Canvas: TCanvas);
procedure DrawArrow(const Pt: TPoint; ArrowScale: Integer);
var
ArrowHeight: Integer;
ArrowPts: array[1..3] of TPoint;
begin
if Owner.MarkerSize > Pen.Width then
ArrowHeight := ArrowScale * Owner.MarkerSize
else
ArrowHeight := ArrowScale * Pen.Width;
ArrowPts[1] := Pt;
ArrowPts[2] := Point(pt.X - ArrowHeight div 2, pt.Y - ArrowHeight div 2);
//ArrowPts[3] := Point(pt.X , pt.Y - ArrowHeight div 3);
ArrowPts[3] := Point(pt.X + ArrowHeight div 2, pt.Y - ArrowHeight div 2);
Canvas.Polygon(ArrowPts);
end;
begin
Canvas.Polyline(Puntos);
if Kind <> lkUndirected then
begin
DrawArrow(Puntos[UltPunto], ArrowSize);
if Kind = lkBidirected then
DrawArrow(Puntos[0], -ArrowSize);
end;
end;
procedure TOrtoLink.CalculateEndPoints;
Var i,x1,y1,x2,y2: integer;
begin
if (FromNode <> nil) and (ToNode <> nil) and (State = osNone) then
begin
x1 := FromNode.Center.X;
y1 := FromNode.Center.Y;
x2 := ToNode.Center.X;
y2 := ToNode.Center.y;
for i := 0 to 5 do Puntos[i] := Point(0,0);
if y2 >y1 then // el destino esta po debajo del origen
begin
if x2 <> x1 then // no estan alineados
begin
Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
Puntos[3] := Point(ToNode.Center.X, ToNode.Top);
Puntos[4] := Puntos[3];
Puntos[5] := Puntos[3];
// cuidao que este se haga despuesd de pUntos[3] sino valdra 0
Puntos[2] := Point(Puntos[3].X, Puntos[1].y);
UltPunto := 3;
fStartPt := Puntos[1];
fEndPt := Puntos[2];
fAngle := 0;
end
else// estan alineados
begin
Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
Puntos[1] := Point(ToNode.Center.X, ToNode.Top);
Puntos[2] := Puntos[1];
Puntos[3] := Puntos[1];
Puntos[4] := Puntos[1];
Puntos[5] := Puntos[1];
// cuidao que este se haga despuesd de pUntos[3] sino valdra 0
UltPunto := 2;
fStartPt := Puntos[0];
fEndPt := Puntos[1];
fAngle := pi / 2;
end;
end
else //if y2 >y1 then
begin // el destino esta por encima del origen
if x2 < x1 then
begin
Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
Puntos[2] := Point(10+ FromNode.Center.X + FromNode.Width div 2 , Puntos[1].y);
Puntos[3] := Point(Puntos[2].x,ToNode.Top -10);
Puntos[4] := Point(ToNode.Center.X, ToNode.Top -10);
Puntos[5] := Point(ToNode.Center.X, ToNode.Top );
// cuidao que este se haga despuesd de pUntos[3] sino valdra 0
UltPunto := 5;
end
else
begin
Puntos[0] := Point(FromNode.Center.X, FromNode.Top + FromNode.Height);
Puntos[1] := Point(Puntos[0].X , Puntos[0].y +10);
Puntos[2] := Point( FromNode.Center.X - FromNode.Width div 2 -10 , Puntos[1].y);
Puntos[3] := Point(Puntos[2].x,ToNode.Top -10);
Puntos[4] := Point(ToNode.Center.X, ToNode.Top -10);
Puntos[5] := Point(ToNode.Center.X, ToNode.Top );
// cuidao que este se haga despuesd de pUntos[3] sino valdra 0
UltPunto := 5;
end;
fStartPt := Puntos[2];
fEndPt := Puntos[3];
end;
CalculateTextParameters(True, 0, 0);
end;
end;
function TOrtoLink.GetTextRegion: HRGN;
const
DrawTextFlags = DT_NOPREFIX or DT_END_ELLIPSIS or DT_EDITCONTROL or
DT_MODIFYSTRING or DT_CALCRECT;
var
RgnPts: array[1..4] of TPoint;
ArrowHeight: Integer;
LineWidth: Integer;
TextRect: TRect;
TmpText: String;
begin
Result := 0;
TextToShow := '';
if (Text <> '') and (FromNode <> nil) and (ToNode <> nil) then
begin
if Owner.MarkerSize > Pen.Width then
ArrowHeight := 4 * Owner.MarkerSize
else
ArrowHeight := 4 * Pen.Width;
LineWidth := Trunc(Sqrt(Sqr(StartPt.X - EndPt.X) + Sqr(StartPt.Y - EndPt.Y)));
if LineWidth > 3 * ArrowHeight then
begin
Dec(LineWidth, 3 * ArrowHeight);
SetRect(TextRect, 0, 0, LineWidth, 0);
Owner.Canvas.Font := Font;
TmpText := Trim(Text);
SetLength(TmpText, Length(TmpText) + 4);
Windows.DrawText(Owner.Canvas.Handle, PChar(TmpText), -1, TextRect,
Owner.DrawTextBiDiModeFlags(DrawTextFlags));
SetLength(TmpText, StrLen(PChar(TmpText)));
TextToShow := TmpText;
TextCenter.X := (StartPt.X + EndPt.X) div 2;
TextCenter.Y := StartPt.Y;//(StartPt.Y + EndPt.Y) div 2;
TextCenter := NextPointOfLine(Angle - Pi / 2, TextCenter, TextRect.Top);
OffsetRect(TextRect, TextCenter.X - TextRect.Right div 2,
TextCenter.Y - TextRect.Bottom);
RgnPts[1] := TextRect.TopLeft;
RgnPts[2] := Point(TextRect.Right, TextRect.Top);
RgnPts[3] := TextRect.BottomRight;
RgnPts[4] := Point(TextRect.Left, TextRect.Bottom);
if Abs(Angle) > Pi / 2 then
RotatePoints(RgnPts, Angle - Pi, TextCenter)
else
RotatePoints(RgnPts, Angle, TextCenter);
Result := CreatePolygonRgn(RgnPts, 4, ALTERNATE);
end;
end;
end;
Kambiz wrote:
- Implemented but needs some adjustments: Links not only can be between two nodes, but also can be between a link and a node, or even between two links.
elias wrote:Kambiz wrote:
- Implemented but needs some adjustments: Links not only can be between two nodes, but also can be between a link and a node, or even between two links.
That's good, really; I was indeed going to implement this in my .pas!!
Return to DELPHI AREA Projects
Users browsing this forum: No registered users and 2 guests