DDHGRAPH.PAS

unit DdhGraph;

interface

{$R *.DCR}

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls,
  Forms, Dialogs;

type
  TDdhGraph = class; // forward declaration

  TDdhPoint = class (TCollectionItem)
  private
    fX, fY: Integer;
  public
    Text: string;
    procedure WriteText (Writer: TWriter);
    procedure ReadText (Reader: TReader);
    procedure DefineProperties (Filer: TFiler); override;
    procedure Paint (Canvas: TCanvas);
    procedure Assign (Pt: TPersistent); override;
  published
    property X: Integer read fX write fX;
    property Y: Integer read fY write fY;
  end;

  TDdhPoints = class (TCollection)
  private
    fGrid: TDdhGraph;
    function GetItem (Index: Integer): TDdhPoint;
    procedure SetItem (Index: Integer; Value: TDdhPoint);
  protected
    procedure Update (Item: TCollectionItem); override;
  public
    constructor Create (Grid: TDdhGraph);
    function Add: TDdhPoint;
    property Items [Index: Integer]: TDdhPoint
      read GetItem write SetItem; default;
  end;

  TDdhGraph = class(TGraphicControl)
  private
    fPoints: TDdhPoints;
    fDefText: string;
    fBorderStyle: TBorderStyle;
    fLinesColor: TColor;
  protected
    procedure SetBorderStyle (Value: TBorderStyle);
    procedure SetLinesColor (Value: TColor);
    procedure MouseDown (Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer); override;
  public
    constructor Create (Owner: TComponent); override;
    destructor Destroy; override;
    procedure Paint; override;
  published
    property Color; // fill color
    property LinesColor: TColor
      read fLinesColor write SetLinesColor
      default clBlack;
    property Font;
    property Align;
    property DefaultText: string
      read fDefText write fDefText;
    property BorderStyle: TBorderStyle
      read fBorderStyle write SetBorderStyle
      default bsNone;
    // collection property
    property Points: TDdhPoints
      read fPoints write fPoints;
  end;

procedure Register;

implementation

// TDdhPoint collection item

procedure TDdhPoint.WriteText (Writer: TWriter);
begin
  Writer.WriteString (Text);
end;

procedure TDdhPoint.ReadText (Reader: TReader);
begin
  Text := Reader.ReadString;
end;

procedure TDdhPoint.DefineProperties (Filer: TFiler);
begin
  Filer.DefineProperty (
    'Text', ReadText, WriteText, (Text <> ''));
end;

procedure TDdhPoint.Paint (Canvas: TCanvas);
begin
  if Index > 0 then
    Canvas.LineTo (fX, fY);
  Canvas.Ellipse (fX - 3, fY - 3, fX + 3, fY + 3);
  Canvas.TextOut (fX + 5, fY + 5, Text);
  Canvas.MoveTo (fX, fY);
end;

procedure TDdhPoint.Assign (Pt: TPersistent);
begin
  if Pt is TDdhPoint then
  begin
    fx := TDdhPoint (Pt).fX;
    fY := TDdhPoint (Pt).fY;
    Text := TDdhPoint (Pt).Text;
  end
  else
    // raise an exception
    inherited Assign (pt);
end;

// TDdhPoints collection

constructor TDdhPoints.Create (Grid: TDdhGraph);
begin
  inherited Create (TDdhPoint);
  fGrid := Grid;
end;

function TDdhPoints.Add: TDdhPoint;
begin
  Result := TDdhPoint (inherited Add);
end;

function TDdhPoints.GetItem (
  Index: Integer): TDdhPoint;
begin
  Result := TDdhPoint (inherited GetItem (Index));
end;

procedure TDdhPoints.SetItem (
  Index: Integer; Value: TDdhPoint);
begin
  inherited SetItem (Index, Value);
end;

procedure TDdhPoints.Update (
  Item: TCollectionItem);
begin
  if Item <> nil then
    fGrid.Invalidate;
end;

// TDdhGraph component

constructor TDdhGraph.Create (Owner: TComponent);
begin
  inherited Create (Owner);
  fPoints := TDdhPoints.Create (self);
  fDefText := 'Pt';
  fBorderStyle := bsNone;
  fLinesColor := clBlack;
  // desing time right clicks = left clicks
  ControlStyle := ControlStyle + [csDesignInteractive];
end;

destructor TDdhGraph.Destroy;
begin
  fPoints.Free;
  fPoints := nil;
  inherited Destroy;
end;

procedure TDdhGraph.SetBorderStyle (Value: TBorderStyle);
begin
  if Value <> fBorderStyle then
  begin
    fBorderStyle := Value;
    Invalidate;
  end;
end;

procedure TDdhGraph.SetLinesColor (Value: TColor);
begin
  if Value <> fLinesColor then
  begin
    fLinesColor := Value;
    Invalidate;
  end;
end;

procedure TDdhGraph.MouseDown (Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var
  Pt: TDdhPoint;
begin
  if (not (csDesigning in ComponentState)) or
    ((csDesigning in ComponentState) and
    (ssCtrl in Shift)) then
  begin
    Pt := fPoints.Add;
    Pt.X := X;
    Pt.Y := Y;
    Pt.Text := Format ('%s%d', [fDefText, fPoints.Count]);
    Invalidate;
  end;
end;

procedure TDdhGraph.Paint;
var
  I: Integer;
begin
  // values used when drawing the points
  with Canvas do
  begin
    Brush.Color := Color;
    Pen.Color := fLinesColor;
    Pen.Style := psSolid;
    Font.Assign (self.Font);
  end;

  // draw the points
  for I := 0 to fPoints.Count - 1 do
    fPoints.Items[I].Paint (Canvas);

  // eventually draw a border
  with Canvas do
    // at design time
    if csDesigning in ComponentState then
    begin
      Pen.Color := clBlack;
      Pen.Style := psDash;
      Brush.Style := bsClear;
      Rectangle (0, 0, Width, Height);
    end
    // at run time
    else if BorderStyle = bsSingle then
    begin
      Pen.Color := clBlack;
      Pen.Style := psSolid;
      Brush.Style := bsClear;
      Rectangle (0, 0, Width, Height);
    end;
end;

procedure Register;
begin
  RegisterComponents ('DDHB', [TDdhGraph]);
end;

end.

Generated by PasToWeb, a tool by Marco Cantù.