unit graphdisplay;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  StdCtrls,genericGraph;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    toStr: TButton;
    fromStr: TButton;
    Memo1: TMemo;
    PaintBox1: TPaintBox;
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure fromStrClick(Sender: TObject);
    procedure toStrClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure PaintBox1Paint(Sender: TObject);
  private
    { private declarations }
    procedure ValueToString(sender:TObject; value: TGraphValueType; var s: string);
    procedure StringToValue(sender:TObject; s: string; var value: TGraphValueType);
  public
    { public declarations }
    graph:TGraph;
    selected:TGraphNode;
    lastSelected: TGraphNode;
    marked:TGraphNodes;
    procedure drawGraph;
  end; 

var
  Form1: TForm1; 

implementation

{ TForm1 }

function valueToX(v: TGraphValueType):longint;
begin
  result:=v div 1000000;
end;
function valueToY(v: TGraphValueType):longint;
begin
  result:=(v mod 1000000) div 1000;
end;
{function xToValue(x:longint):TGraphValueType;
begin
  result:=x* 1000000;
end;
function yToValue(y:longint):TGraphValueType;
begin
  result:=y* 1000;
end;                       }
function xyToValue(x,y:longint):TGraphValueType;
begin
  result:=x* 1000000+y*1000;
end;



procedure TForm1.Button1Click(Sender: TObject);
begin
  graph.addValue(xyToValue(PaintBox1.Width div 2+random(100)-50,PaintBox1.Height div 2+random(100)-50));
  Refresh;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  marked:=graph.findShortestPath(lastSelected,selected).nodes;
  drawGraph;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  graph.createBackLinks;
  drawGraph;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  graph.createBackLinks;
  marked:=graph.findArticulationPoints();
  drawGraph;
end;

procedure TForm1.fromStrClick(Sender: TObject);
begin
  graph.loadFromString(Memo1.Lines.Text);
  drawGraph;
end;

procedure TForm1.toStrClick(Sender: TObject);
begin
  memo1.Lines.Text:=graph.saveToString;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  graph:=TGraph.Create;
  graph.onStringToValue:=@StringToValue;
  graph.onValueToString:=@ValueToString;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  graph.free;
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
  function findAt(x,y:longint):TGraphNode;
  var i:longint;
  begin
    result:=nil;
    for i:=0 to high(graph.nodes) do
      if sqr(valueToX(graph.nodes[i].value)-x)+sqr(valueToY(graph.nodes[i].value)-y)<=sqr(15) then
        result:=graph.nodes[i];
  end;
begin
  if button=mbLeft then
    if ssCtrl in shift then graph.addLink(selected,findAt(x,y))
    else begin
      lastSelected:=selected;
      selected:=findAt(x,y);
      setlength(marked,0);
    end;
  drawGraph;
end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  if ssLeft in shift then begin
    if selected=nil then exit;
    selected.value:=xyToValue(x,y);
    drawGraph;
  end;
end;

procedure TForm1.PaintBox1Paint(Sender: TObject);
begin
  drawGraph;
end;

procedure TForm1.ValueToString(sender: TObject; value: TGraphValueType;
  var s: string);
begin
  s:=IntToStr(value);
end;

procedure TForm1.StringToValue(sender: TObject; s: string;
  var value: TGraphValueType);
begin
  value:=StrToInt(s);
end;

procedure TForm1.drawGraph;
var i,j:longint;
    can: TCanvas;
begin
  can:=PaintBox1.Canvas;
  can.brush.Color:=clBtnFace;
  can.FillRect(PaintBox1.BoundsRect);
  for i:=0 to high(graph.nodes) do begin
    if graph.nodes[i]=selected then can.brush.Color:=$00FF00
    else if graph.nodes[i]=lastselected then can.brush.Color:=$AAFFAA
    else if graph.gnFind(marked,graph.nodes[i])<>-1 then can.brush.Color:=$0000AA
    else can.brush.Color:=clwhite;
    can.EllipseC(valueToX(graph.nodes[i].value),valueToY(graph.nodes[i].value),15,15);
    can.TextOut(valueToX(graph.nodes[i].value),valueToY(graph.nodes[i].value),IntToStr(graph.nodes[i]._visit));
  end;
  for i:=0 to high(graph.nodes) do
    for j:=0 to high(graph.nodes[i].links) do
      can.Arrow(valueToX(graph.nodes[i].value),valueToY(graph.nodes[i].value),
                valueToX(graph.nodes[i].links[j].value),valueToY(graph.nodes[i].links[j].value),
                10,45*16);
end;

initialization
  {$I graphdisplay.lrs}

end.

