Recent

Author Topic: IDE: Missing Line Objects in TShape?  (Read 10545 times)

IPguy

  • Sr. Member
  • ****
  • Posts: 385
IDE: Missing Line Objects in TShape?
« on: April 12, 2011, 01:34:56 am »
I have been unable to find a line object in the IDE.

I've used TShape to make a dividing line between two sections within a form, but that was more work than it should have been.  I added a stRectangle and flattened it.  Hard to click on that object in the IDE and I could not create a "fat" line just using Pen.Width.  To get a decent heavy line I had to set the Pen.Width to something large (like 4 or more) and then set the Height to ~4. 

And there are no arrow ends.
And I do not see a way to rotate the "line" (rectangle) object.

How do others add lines and arrows to your projects?

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: IDE: Missing Line Objects in TShape?
« Reply #1 on: April 12, 2011, 01:42:00 am »
You could add a feature request on BugTracker and even help to write the component.

Or you could convert a Delphi component or draw the line by yourself.

Here is the Paint procedure of TShape.

Code: [Select]
procedure TShape.Paint;
var
  PaintRect: TRect;
  MinSize: Longint;
  P: array[0..3] of TPoint;
  PenInc, PenDec: Integer;
begin
  with Canvas do
  begin
    Pen := FPen;
    Brush := FBrush;

    PenInc := Pen.Width div 2;
    PenDec := (Pen.Width - 1) div 2;

    PaintRect := Rect(PenInc, PenInc, Self.Width - PenDec, Self.Height - PenDec);
    with PaintRect do
    begin
      MinSize := Min(Right - Left, Bottom - Top);
      if FShape in [stSquare, stRoundSquare, stCircle, stSquaredDiamond] then
      begin
        Left := Left + ((Right - Left) - MinSize) div 2;
        Top := Top + ((Bottom - Top) - MinSize) div 2;
        Right := Left + MinSize;
        Bottom := Top + MinSize;
      end;
    end;

    case FShape of
      stRectangle, stSquare:
        Rectangle(PaintRect);
      stRoundRect, stRoundSquare:
        RoundRect(PaintRect, MinSize div 4, MinSize div 4);
      stCircle, stEllipse:
        Ellipse(PaintRect);
      stSquaredDiamond, stDiamond:
      begin
        with Self do
        begin
          P[0].x := PenInc;
          P[0].y := (Height - 1) div 2;
          P[1].x := (Width - 1) div 2;
          P[1].y := PenInc;
          P[2].x := Width - PenInc - 1;
          P[2].y := P[0].y;
          P[3].x := P[1].x;
          P[3].y := Height - PenInc - 1;
          Polygon(P);
        end;
      end;
      stTriangle:
      begin
        with Self do
        begin
          P[0].x := (Width - 1) div 2;
          P[0].y := PenInc;
          P[1].x := Width - PenInc - 1;
          P[1].y := Height - PenInc - 1;
          P[2].x := PenInc;
          P[2].y := Height - PenInc - 1;
          P[3].x := P[0].x;
          P[3].y := P[0].y;
          Polygon(P);
        end;
      end;
    end;
  end;
  // to fire OnPaint event
  inherited Paint;
end;   

You could add you code here and commit it on BugTracker.
« Last Edit: April 12, 2011, 01:54:21 am by typo »

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: IDE: Missing Line Objects in TShape?
« Reply #2 on: April 12, 2011, 01:55:55 am »
If no one comes up with a solution, I will add a feature request, but I want to be sure that I have not overlooked something in the IDE first.

I used Delphi back in the v2 (?) days and I no longer have the software or the license key. 

The "do it myself" option is interesting and it would help me learn the internals, but I have to get my product out the door first before I can "play".

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: IDE: Missing Line Objects in TShape?
« Reply #3 on: April 12, 2011, 01:58:48 am »
typo,
Thanks for the code. 

I just submitted a bug report for two of the shapes disappearing with certain height and pen.width combinatioins.  I'll look into the code to see if I can figure out why that is happening.

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Re: IDE: Missing Line Objects in TShape?
« Reply #4 on: April 12, 2011, 02:11:41 am »
There are components TDividerBevel (in LazControls) or TBevel (as bsTopLine or bsBottomLine) for those purposes.

To reported bug: if TShape.Height is 10 and Pen.Width is 11 then it disappears too. (Always when Pen.Width=Shape.Height+1)
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

IPguy

  • Sr. Member
  • ****
  • Posts: 385
Re: IDE: Missing Line Objects in TShape?
« Reply #5 on: April 12, 2011, 02:16:26 am »
Thanks Blaazen,
I'll add that information to the bug report.

And I will try the T*Bevel objects.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: IDE: Missing Line Objects in TShape?
« Reply #6 on: April 12, 2011, 03:53:42 am »

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: IDE: Missing Line Objects in TShape?
« Reply #7 on: April 12, 2011, 09:03:44 pm »
This unit implements a TLine component: 

Code: [Select]
// Initially developed by Gon Perez-Jimenez. 2002-4th-April for Delphi
unit ULine;

interface

uses
   SysUtils, Classes, Controls, Graphics;

type
  TLineDirection = (drLeftRight, drUpDown, drTopLeftBottomRight, drTopRightBottomLeft);

  TLine = class(TGraphicControl)
  private
    { Private declarations }
    FLineDir: TLineDirection;
    FArrow1: Boolean;
    FArrow2: Boolean;
    FArrowFactor: Integer;
    function GetLineWidth: Integer;
    function GetLineColor: TColor;
    function GetLineStyle: TPenStyle;
    procedure SetLineWidth(const NewWidth: Integer);
    procedure SetLineColor(const NewColor: TColor);
    procedure SetLineDir(const NewDir: TLineDirection);
    procedure SetArrow1(Value: Boolean);
    procedure SetArrow2(Value: Boolean);
    procedure SetArrowFactor(Value: integer);
    procedure SetLineStyle(const NewStyle: TPenStyle);
  protected
    { Protected declarations }
    procedure Paint; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published declarations }
    property DragCursor;
    property DragKind;
    property DragMode;
    property Align;
    property ParentShowHint;
    property Hint;
    property ShowHint;
    property Visible;
    property PopupMenu;
    property Direction: TLineDirection read FLineDir write SetLineDir default drLeftRight;
    property Color: TColor read GetLineColor write SetLineColor;
    property LineStyle :TPenStyle read GetLineStyle write SetLineStyle;
    property LineWidth: Integer read GetLineWidth write SetLineWidth;
    property Arrow1: Boolean read FArrow1 write SetArrow1 default False;
    property Arrow2: Boolean read FArrow2 write SetArrow2 default False;
    property ArrowFactor: Integer read FArrowFactor write SetArrowFactor default 3;
    property OnDragDrop;
    property OnDragOver;
    property OnEndDrag;
    property OnEndDock;
    property OnMouseDown;
    property OnMouseMove;
    property OnMouseUp;
    property OnClick;
    property OnDblClick;
  end;

procedure Register;

implementation

{ TLine }

constructor TLine.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ControlStyle := ControlStyle + [csReplicatable];
  Width := 65;
  Height := 4;
  Canvas.Brush.Color:=clBlack;
  FArrowFactor:=3;
end;

destructor TLine.Destroy;
begin
  inherited Destroy;
end;

procedure TLine.SetArrowFactor(Value: Integer);
begin
  if Value <> FArrowFactor then begin
     FArrowFactor := Value;
     Invalidate;
  end;
end;

procedure TLine.SetArrow1(Value: Boolean);
begin
  if Value <> FArrow1 then begin
     FArrow1 := Value;
     if Value then SetLineWidth(1);
     Invalidate;
  end;
end;

procedure TLine.SetArrow2(Value: Boolean);
begin
  if Value <> FArrow2 then begin
     FArrow2 := Value;
     if Value then SetLineWidth(1);
     Invalidate;
  end;
end;

function TLine.GetLineWidth: Integer;
begin
  Result := Canvas.Pen.Width;
end;

function TLine.GetLineColor: TColor;
begin
  Result := Canvas.Pen.Color;
end;

function TLine.GetLineStyle: TPenStyle;
begin
  Result := Canvas.Pen.Style;
end;

procedure TLine.SetLineWidth(const NewWidth: Integer);
begin
  if NewWidth <> Canvas.Pen.Width then
  begin
    if FArrow1 or FArrow2 then begin
       //LineWidth:=1;  // stack overflow
       Canvas.Pen.Width:=1;
    end else Canvas.Pen.Width := NewWidth;
    Invalidate;
  end;
end;

procedure TLine.SetLineColor(const NewColor: TColor);
begin
  if NewColor <> Canvas.Pen.Color then
  begin
    Canvas.Pen.Color := NewColor;
    Invalidate;
  end;
end;

procedure TLine.SetLineStyle(const NewStyle: TPenStyle);
begin
  if NewStyle <> Canvas.Pen.Style then
  begin
    Canvas.Pen.Style := NewStyle;
    Invalidate;
  end;
end;

procedure TLine.SetLineDir(const NewDir: TLineDirection);
begin
  if NewDir <> FLineDir then
  begin
    FLineDir := NewDir;
    Invalidate;
  end;
end;

procedure TLine.Paint;
var
  start: Integer;
  p1,p2,p3:TPoint;
  H0,W0,H,W:Integer;
  Alfa:extended;
begin
  inherited;
  case FLineDir of
    drLeftRight:
      begin
        start := (Height - Canvas.Pen.Width) div 2;
        Canvas.Brush.Style := bsClear;
        Canvas.MoveTo(0, start);
        Canvas.LineTo(Width, Start);
        if FArrow1 then begin
          // Arrow left
          p1:=Point(0,start);
          p2:=Point(FArrowFactor,Start-FArrowFactor);
          p3:=Point(FArrowFactor,Start+FArrowFactor);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;

        if FArrow2 then begin
          // Arrow right
          p1:=Point(Width-1, Start);
          p2:=Point(Width-(FArrowFactor+1),Start-FArrowFactor);
          p3:=Point(Width-(FArrowFactor+1),Start+FArrowFactor);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
      end;
    drUpDown:
      begin
        start := (Width - Canvas.Pen.Width) div 2;
        Canvas.Brush.Style := bsClear;
        Canvas.MoveTo(start, 0);
        Canvas.LineTo(start, Height);
        if FArrow1 then begin
          // Arrow up
          p1:=Point(start,0);
          p2:=Point(Start-FArrowFactor,FArrowFactor);
          p3:=Point(Start+FArrowFactor,FArrowFactor);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;

        if FArrow2 then begin
          // Arrow down
          p1:=Point(start,Height-1);
          p2:=Point(Start-FArrowFactor,Height-(FArrowFactor+1));
          p3:=Point(Start+FArrowFactor,Height-(FArrowFactor+1));
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
      end;
    drTopLeftBottomRight:
      begin
        Canvas.Brush.Style := bsClear;
        Canvas.MoveTo(0, 0);
        Canvas.LineTo(Width, Height);
        if FArrow1 and(Width>0)then begin
          // Arrow up
          Alfa:=ArcTan(Height/Width);
          H0:=Round((FArrowFactor+1)*Sin(Alfa));
          W0:=Round((FArrowFactor+1)*Cos(Alfa));
          p1:=Point(0,0);
          W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
          if H<0 then H:=0;
          if W<0 then W:=0;
          p2:=Point(W,H);
          W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
          if H<0 then H:=0;
          if W<0 then W:=0;
          p3:=Point(W,H);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
        if FArrow2 and(Width>0)then begin
          // Arrou down
          Alfa:=ArcTan(Height/Width);
          H0:=Round((FArrowFactor+1)*Sin(Alfa));
          W0:=Round((FArrowFactor+1)*Cos(Alfa));
          p1:=Point(Width-1, Height-1);
          W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
          W:=Width-W-1;
          H:=Height-H-1;
          if H>=Height then H:=Height-1;
          if W>=Width then W:=Width-1;
          p2:=Point(W,H);
          W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
          W:=Width-W-1;
          H:=Height-H-1;
          if H>=Height then H:=Height-1;
          if W>=Width then W:=Width-1;
          p3:=Point(W,H);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
      end;
    drTopRightBottomLeft:
      begin
        Canvas.Brush.Style := bsClear;
        Canvas.MoveTo(Width, 0);
        Canvas.LineTo(0, Height);
        if FArrow1 and(Width>0)then begin
          // Arrou up
          Alfa:=ArcTan(Height/Width);
          H0:=Round((FArrowFactor+1)*Sin(Alfa));
          W0:=Round((FArrowFactor+1)*Cos(Alfa));
          p1:=Point(Width-1,0);
          W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
          W:=Width-W-1;
          if H<0 then H:=0;
          if W>=Width then W:=Width-1;
          p2:=Point(W,H);
          W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
          W:=Width-W-1;
          if H<0 then H:=0;
          if W>=Width then W:=Width-1;
          p3:=Point(W,H);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
        if FArrow2 and(Width>0)then begin
          // Arrow down
          Alfa:=ArcTan(Height/Width);
          H0:=Round((FArrowFactor+1)*Sin(Alfa));
          W0:=Round((FArrowFactor+1)*Cos(Alfa));
          p1:=Point(0, Height-1);
          W:=Round(W0-(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0+(FArrowFactor*Sin((Pi/2)-Alfa)));
          H:=Height-H-1;
          if H>=Height then H:=Height-1;
          if W<0 then W:=0;
          p2:=Point(W,H);
          W:=Round(W0+(FArrowFactor*Cos((Pi/2)-Alfa)));
          H:=Round(H0-(FArrowFactor*Sin((Pi/2)-Alfa)));
          H:=Height-H-1;
          if H>=Height then H:=Height-1;
          if W<0 then W:=0;
          p3:=Point(W,H);
          Canvas.Brush.Style := bsSolid;
          Canvas.Brush.Color := Canvas.Pen.Color;
          Canvas.Polygon([p1,p2,p3]);
        end;
      end;
  end;
end;

procedure Register;
begin
  RegisterComponents('Misc', [TLine]);
end;

end.             

Maybe TShape is not the better place to put a line, since TLine should have properties like Direction or Arrow which are not present on the other kind of shapes. Maybe a standard horizontal line with right arrow could be made by TShape object.
« Last Edit: April 13, 2011, 01:17:49 am by typo »

 

TinyPortal © 2005-2018