unit _main_cursor;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls, ExtCtrls, ImgList, ExtDlgs,
  Menus, ActnList, StdCtrls, Spin,
  ExtEdit, Buttons, DrawComboBox,
  SchemePaintObjects, SchemeVisual,SchemeVisualCursor,
  SchemePaintBmpObjects;

type
  TFormMain = class(TForm)
    StatusBar1: TStatusBar;
    PageControl1: TPageControl;
    Panel1: TPanel;
    SaveDialog1: TSaveDialog;
    OpenDialog1: TOpenDialog;
    OpenPictureDialog1: TOpenPictureDialog;
    ImageList1: TImageList;
    ActionList1: TActionList;
    ActionCenter: TAction;
    ActionZoomIn: TAction;
    ActionZoomOut: TAction;
    ActionZoomActual: TAction;
    ActionPictuteA: TAction;
    PopupMenu1: TPopupMenu;
    ZoomIn1: TMenuItem;
    ZoomOut1: TMenuItem;
    ActionZoomActual1: TMenuItem;
    N2: TMenuItem;
    Center1: TMenuItem;
    TabSheet2: TTabSheet;
    Panel2: TPanel;
    CheckBox1: TCheckBox;
    FloatEdit3: TFloatEdit;
    Label2: TLabel;
    Label38: TLabel;
    FloatEdit9: TFloatEdit;
    Label3: TLabel;
    Panel3: TPanel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    CheckBox2: TCheckBox;
    FloatEdit4: TFloatEdit;
    FloatEdit5: TFloatEdit;
    BitBtn10: TBitBtn;
    SchemeVisualEditorCursor1: TSchemeVisualEditorCursor;
    SchemeVisualEditorCursor2: TSchemeVisualEditorCursor;
    SchemeDataEditorCursor1: TSchemeDataEditorCursor;
    Splitter1: TSplitter;
    ImageListImages: TImageList;
    ImageListImagesMask: TImageList;
    ActionResized: TAction;
    N1: TMenuItem;
    ResizeobjectOnOff1: TMenuItem;
    ActionSelected: TAction;
    SelectedOnOff1: TMenuItem;
    Label1: TLabel;
    SpinEdit3: TSpinEdit;
    CheckBox3: TCheckBox;
    CheckBox4: TCheckBox;
    ActionReload: TAction;
    Reload1: TMenuItem;
    N3: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure SchemeDataEditorCursor1MouseDown(Sender, VisualSender: TObject;
      Button: TMouseButton; Shift: TShiftState;
      AObject: TAbstractPaintObject);
    procedure PopupMenu1Popup(Sender: TObject);
    procedure ActionCenterExecute(Sender: TObject);
    procedure ActionZoomInExecute(Sender: TObject);
    procedure ActionPictuteAExecute(Sender: TObject);
    procedure CheckBox1Click(Sender: TObject);
    procedure FloatEdit3Change(Sender: TObject);
    procedure FloatEdit9Change(Sender: TObject);
    procedure CheckBox2Click(Sender: TObject);
    procedure FloatEdit4Change(Sender: TObject);
    procedure FloatEdit5Change(Sender: TObject);
    procedure SchemeVisualEditorCursor1MouseDown(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure SchemeVisualEditorCursor1MouseMove(Sender: TObject;
      Shift: TShiftState; X, Y: Integer);
    procedure SchemeVisualEditorCursor1MouseUp(Sender: TObject;
      Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
    procedure SchemeDataEditorCursor1ObjectCanDrop(Sender,
      VisualSender: TObject; Shift: TShiftState;
      AObject: TAbstractPaintObject; X, Y, OffsetX, OffsetY: Extended;
      var AEnabled: Boolean);
    procedure ActionResizedExecute(Sender: TObject);
    procedure ActionSelectedExecute(Sender: TObject);
    procedure SpinEdit3Change(Sender: TObject);
    procedure CheckBox3Click(Sender: TObject);
    procedure CheckBox4Click(Sender: TObject);
    procedure SchemeDataEditorCursor1ObjectPaint(Sender,
      VisualSender: TObject; AObject: TAbstractPaintObject;
      AZoom: Extended; ACanvas: TCanvas; AParam: Integer);
    procedure ActionReloadExecute(Sender: TObject);
  private
    pCurrentPoint:TPoint;
    pSelectedObject:TAbstractPaintObject;            //тот который изменяем
    pSelectedSchemeVisualEditor:TSchemeVisualEditorCursor; //окно с которым работаем
    procedure CreateAll;
    procedure CreateLayer(AId:integer);
    procedure SetLayerParams(AId:integer);
    procedure CreateZonenObjects;
    procedure CreateSmallObjects;
    procedure CreateBmpObjects;
    procedure CreateStretchBmpObjects;
    procedure CreateTextObjects;
    procedure CreateArrowObjects;
    procedure SetCurrentPoint(X,Y:integer);
    procedure SetSelectedObject(Value:TObject);
    procedure SetSelectedSchemeVisual(Value:TObject);
    procedure UpdateStatusBarInfo;
    procedure TestEnabledActions;
  public
  end;

var
  FormMain: TFormMain;

//================================================================
implementation
{$R *.DFM}
uses _cv;
const

  ciZoneLayerId       = 0;
  ciSmallLayerId      = 1;
  ciBmpLayerId        = 2;
  ciStretchBmpLayerId = 3;
  ciTextLayerId       = 4;
  ciArrowLayerId      = 5;

  ciZoneW         = 150;
  ciZoneH         = 150;

  ciCenterW       = 150;
  ciCenterH       = 150;

  ciSmallW        = ciCenterW div 10;
  ciSmallH        = ciCenterH div 10;

  ciBmpW          = 32;
  ciBmpH          = 32;

  ciTextH         = 14;

//-------------------------- Form -------------------------

procedure TFormMain.FormCreate(Sender: TObject);
begin
  with Constraints do
  begin
    MinHeight:=Height;
    MinWidth:=Width;
  end;
  crWindowZoomDeltaB:=1;
  StatusBar1.Panels[1].Text := Format('Zoom A:%.1f  B:%.1f',
    [SchemeVisualEditorCursor1.Zoom,
    SchemeVisualEditorCursor2.Zoom]);
  TestEnabledActions;
  CreateAll;
  WindowState:=wsMaximized;
end;

//-------------------- Common -----------------------

procedure TFormMain.CreateAll;
begin
  with SchemeDataEditorCursor1 do
  try
    BeginUpdate;
    SetSelectedObject(nil);
    CreateZonenObjects;
    CreateSmallObjects;
    CreateBmpObjects;
    CreateStretchBmpObjects;
    CreateTextObjects;
    CreateArrowObjects;
  finally
    EndUpdate;
    RepaintAllVisualControls;
  end;
end;

procedure TFormMain.CreateLayer(AId:integer);
begin
  with SchemeDataEditorCursor1 do
  begin
    try
      LayerDelete(AId);
    except
    end;
    LayerAdd(AId);
    SetLayerParams(AId);
  end;
end;

procedure TFormMain.SetLayerParams(AId:integer);
begin
  with SchemeDataEditorCursor1 do
  try
    //BeginUpdate;     //if necessary
    Layer[AId].MinZoomForText:=10;
    Layer[AId].EnabledZoomForText:=false;
    LayerSetAllStateColors(AId,aclStateColors);
  finally
    //EndUpdate;
    //RepaintAllVisualControls;
  end;
end;

procedure TFormMain.CreateZonenObjects;
begin
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciZoneLayerId);
    Layer[ciZoneLayerId].Enabled:=false;
    //--- create 0 zone:
    ObjectAddZone(ciZoneLayerId,
      0, //Id
      [Point(ciZoneW,0),Point(ciZoneW,ciZoneH),Point(0,ciZoneH)],//Points array
      0, //State
      bsDiagCross,//TBrushStyle;
      '',//Text string;
      Point(0,0));//Text string point
    Layer[ciZoneLayerId].Items[0].HintString:=
      'TPaintObjectZone'#13'Object Id : 0'#13'State : 0';
    //--- create 1 zone:
    ObjectAddZone(ciZoneLayerId, 1,
      [Point(ciZoneW+ciCenterW,0),
        Point(ciZoneW+ciCenterW+ciZoneW,ciZoneH),
        Point(ciZoneW+ciCenterW,ciZoneH)],//Points array
      1, bsDiagCross, '', Point(0,0));
    Layer[ciZoneLayerId].Items[1].HintString:=
      'TPaintObjectZone'#13'Object Id : 1'#13'State : 1';
    //--- create 2 zone:
    ObjectAddZone(ciZoneLayerId, 2,
      [Point(0,ciZoneH+ciCenterH),
        Point(ciZoneW,ciZoneH+ciCenterH),
        Point(ciZoneW,ciZoneH+ciCenterH+ciZoneH)],//Points array
      2, bsDiagCross, '', Point(0,0));
    Layer[ciZoneLayerId].Items[2].HintString:=
      'TPaintObjectZone'#13'Object Id : 2'#13'State : 2';
    //--- create 3 zone:
    ObjectAddZone(ciZoneLayerId, 3,
      [Point(ciZoneW+ciCenterW,ciZoneH+ciCenterH),
        Point(ciZoneW+ciCenterW+ciZoneW,ciZoneH+ciCenterH),
        Point(ciZoneW+ciCenterW,ciZoneH+ciCenterH+ciZoneH)],
      3, bsDiagCross, '', Point(0,0));
    Layer[ciZoneLayerId].Items[3].HintString:=
      'TPaintObjectZone'#13'Object Id : 3'#13'State : 3';
  end;
end;

procedure TFormMain.CreateSmallObjects;
var i,j,k:integer;
begin
  k:=0;
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciSmallLayerId);
    for i:=0 to 3 do
      for j:=0 to 4 do
      begin
        ObjectAddShape(ciSmallLayerId,k,
          Bounds(
            ciCenterW+random(9)*(ciSmallW),
            ciCenterH+random(9)*(ciSmallH),
            ciSmallW,ciSmallH),
          i,stRectangle);
        Layer[ciSmallLayerId].Items[k].HintString:=
          Format('TPaintObjectShape'#13'Object ID : %d'#13'State : %d',[k,i]);
        Inc(k);
      end;
  end;
end;

procedure TFormMain.CreateBmpObjects;
var i,j,k:integer;
begin
  k:=0;
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciBmpLayerId);
    for i:=0 to 3 do
      for j:=0 to 1 do
      begin
        ObjectAddDirect(ciBmpLayerId,
          TBmpObject.Create(
            k,             //Object Id
            i+(j*4)+12,    //Image index in ImageListImages
            Bounds(
              ciCenterW+random(9)*(ciBmpW),
              ciCenterH+random(9)*(ciBmpH),
              ciBmpW,ciBmpH),
            i,             //State
            ImageListImages      //ImageList with real images
            ));
        Layer[ciBmpLayerId].Items[k].HintString:=
          Format('TBmpObject'#13'Object ID : %d'#13'State : %d',[k,i]);
        Inc(k);
      end;
  end;
end;

procedure TFormMain.CreateStretchBmpObjects;
var i,j,k:integer;
begin
  k:=0;
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciStretchBmpLayerId);
    for i:=0 to 3 do
      for j:=0 to 2 do
      begin
        ObjectAddDirect(ciStretchBmpLayerId,
          TStretchBmpObject.Create(
            k,             //Object Id
            i+(j*4),       //Image index in ImageListImages
            j,             //Image index in ImageListImagesMask
            Bounds(
              random(9)*(ciBmpW),
              ciCenterH+random(9)*(ciBmpH),
              ciBmpW,ciBmpH),
            i,             //State
            ImageListImages,      //ImageList with real images
            ImageListImagesMask   //ImageList with mask
            ));
        Layer[ciStretchBmpLayerId].Items[k].HintString:=
          Format('TStretchBmpObject'#13'Object ID : %d'#13'State : %d',[k,i]);
        Inc(k);
      end;
  end;
end;

procedure TFormMain.CreateTextObjects;
var i,j,k:integer;
  pText:TPaintObjectText;
begin
  k:=0;
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciTextLayerId);
    for i:=0 to 3 do
      for j:=0 to 2 do
      begin
        pText:=TPaintObjectText.CreateAutoSize
          (k,
          Point(                       //Point
            random(9)*(ciBmpW),
            ciCenterH+random(9)*(ciBmpH)),
          Canvas,
          i,                           //State
          'Simple'#13'Text');
        ObjectAddDirect(ciTextLayerId,pText);
        pText.HintString:=
          Format('TPaintObjectText'#13'Object ID : %d'#13'State : %d',[k,i]);
        Inc(k);
      end;
  end;
end;

procedure TFormMain.CreateArrowObjects;
var i,j,k:integer;
  pArrow:TPaintObjectArrow;
begin
  k:=0;
  with SchemeDataEditorCursor1 do
  begin
    CreateLayer(ciArrowLayerId);
    for i:=0 to 3 do
    begin
      pArrow:=TPaintObjectArrow.CreateExt(
        k,                           //Object Id
        ciCenterW + (ciCenterW div 5)*(i+1),
        ciCenterH div 4,             //Start point
        ciCenterW + (ciCenterW div 5)*(i+1),
        (ciCenterH div 4)*3,         //End point
        1,                           //Width
        i);                          //State
      ObjectAddDirect(ciArrowLayerId,pArrow);
      pArrow.HintString:=
        Format('TPaintObjectArrow'#13'Object ID : %d'#13'State : %d',[k,i]);
      Inc(k);
    end;
  end;
end;


procedure TFormMain.SetCurrentPoint(X,Y:integer);
begin
  pCurrentPoint.X:=X;
  pCurrentPoint.Y:=Y;
end;

procedure TFormMain.UpdateStatusBarInfo;
var s:string;
begin
  s:='';
  if pSelectedObject<>nil then
  with pSelectedObject do
  begin
    s:=Format('For selected object: Layer ID: %d   Object Id: %d    State:%d    Hint: %s',
      [Layer.Id,Id,State,HintString]);
  end;
  StatusBar1.Panels[2].Text:=s;
end;

procedure TFormMain.SetSelectedObject(Value:TObject);
begin
  if pSelectedObject=Value then exit;
  pSelectedObject:=TAbstractPaintObject(Value);
  UpdateStatusBarInfo;
  TestEnabledActions;
end;

procedure TFormMain.SetSelectedSchemeVisual(Value:TObject);
begin
  pSelectedSchemeVisualEditor:=TSchemeVisualEditorCursor(Value);
end;

procedure TFormMain.TestEnabledActions;
var b:boolean;
begin
  b := pSelectedObject<>nil;
  ActionResized.Enabled:=b;
  ActionSelected.Enabled:=b;
end;

procedure TFormMain.PopupMenu1Popup(Sender: TObject);
var p:TPoint;
begin
  GetCursorPos(p);
  p:=pSelectedSchemeVisualEditor.ScreenToClient(p);
  SetCurrentPoint(p.x,p.y);
end;

//--------------------------- Mouse -------------------------

procedure TFormMain.SchemeVisualEditorCursor1MouseDown(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin  // MouseDown
  SetSelectedObject(nil);          //clear old selections
  SetSelectedSchemeVisual(Sender); //window Right or Left
  SetCurrentPoint(X,Y);
end;

procedure TFormMain.SchemeDataEditorCursor1MouseDown(Sender,
  VisualSender: TObject; Button: TMouseButton; Shift: TShiftState;
  AObject: TAbstractPaintObject);
begin //SchemeData   Mouse Down  -> Object selected!
  SetSelectedObject(AObject);
end;

procedure TFormMain.SchemeVisualEditorCursor1MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
var a,b:extended;
begin //Mouse Move
  SetCurrentPoint(0,0);
  a:=x; b:=y;
  TSchemeVisual(Sender).TransformZoomAndOriginXYExt(a,b);//get real
  StatusBar1.Panels[0].Text := Format('%.2f   %.2f',[a,b]);
end;

procedure TFormMain.SchemeVisualEditorCursor1MouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin //Mouse Up
end;

//------------------ Actions --------------------------

procedure TFormMain.ActionCenterExecute(Sender: TObject);
var
  p,p2:TSchemeVisual;
  x,y:integer;
begin //Set centre in others windows
  x:=pCurrentPoint.x;
  y:=pCurrentPoint.y;
  pSelectedSchemeVisualEditor.TransformZoomAndOriginXY(x,y);
  if pSelectedSchemeVisualEditor=SchemeVisualEditorCursor1 then
    p:=SchemeVisualEditorCursor2
  else
    p:=SchemeVisualEditorCursor1;
  p.SetCenterToPoint(Point(X,Y));
end;

procedure TFormMain.ActionZoomInExecute(Sender: TObject);
var
  delta:extended;
  x,y:integer;
  bmovetozenter:boolean;
begin// Zoom
  bmovetozenter:=(pCurrentPoint.x<>0)and(pCurrentPoint.y<>0);
  if bmovetozenter then
  begin //center
    x:=pCurrentPoint.x;
    y:=pCurrentPoint.y;
    pSelectedSchemeVisualEditor.TransformZoomAndOriginXY(x,y);
  end;
  if pSelectedSchemeVisualEditor=SchemeVisualEditorCursor1 then
    delta:=crWindowZoomDeltaA;
  if pSelectedSchemeVisualEditor=SchemeVisualEditorCursor2 then
    delta:=crWindowZoomDeltaB;
  if (TAction(Sender)=ActionZoomOut) then
    delta:=-delta;
  if (TAction(Sender)=ActionZoomActual) then
    delta:=0;
  if delta=0 then pSelectedSchemeVisualEditor.Zoom:=1
  else pSelectedSchemeVisualEditor.Zoom:=pSelectedSchemeVisualEditor.Zoom+delta;
  if bmovetozenter then
  begin //set center
    pSelectedSchemeVisualEditor.SetCenterToPoint(Point(x,y));
  end;
  StatusBar1.Panels[1].Text := Format('Zoom A:%.1f  B:%.1f',
    [SchemeVisualEditorCursor1.Zoom,
    SchemeVisualEditorCursor2.Zoom]);
end;

procedure TFormMain.ActionPictuteAExecute(Sender: TObject);
begin //Picture
  with OpenPictureDialog1 do
  begin
    if not OpenPictureDialog1.Execute then exit;
    SchemeVisualEditorCursor1.Picture.LoadFromFile(FileName);
    SchemeVisualEditorCursor2.Picture.LoadFromFile(FileName);
  end;
end;


//------------------ Page: Windows --------------------------

procedure TFormMain.CheckBox1Click(Sender: TObject);
begin //Enabled editing Window A
  SchemeVisualEditorCursor1.EditEnabled:=CheckBox1.Checked;
end;

procedure TFormMain.FloatEdit3Change(Sender: TObject);
begin //Min size for editing
  SchemeVisualEditorCursor1.MinZoomForResize:=FloatEdit3.Value;
end;

procedure TFormMain.FloatEdit9Change(Sender: TObject);
begin //Delta for zooming A window
  crWindowZoomDeltaA:=FloatEdit9.Value;
end;

procedure TFormMain.CheckBox2Click(Sender: TObject);
begin //Enabled editing Window B
  SchemeVisualEditorCursor2.EditEnabled:=CheckBox2.Checked;
end;

procedure TFormMain.FloatEdit4Change(Sender: TObject);
begin //Min size for editing
  SchemeVisualEditorCursor2.MinZoomForResize:=FloatEdit4.Value;
end;

procedure TFormMain.FloatEdit5Change(Sender: TObject);
begin //Delta for zooming B window
  crWindowZoomDeltaB:=FloatEdit5.Value;
end;

//----------------------- Drag And Drop -------------------

procedure TFormMain.SchemeDataEditorCursor1ObjectCanDrop(Sender,
  VisualSender: TObject; Shift: TShiftState; AObject: TAbstractPaintObject;
  X, Y, OffsetX, OffsetY: Extended; var AEnabled: Boolean);
var p:TAbstractPaintObject;
begin //Can Drop ?                          //as an example
  if AObject is TPaintObjectZone then exit; //enable for all zonen
  if AObject.Resized then exit;             //enabel if resized
  p:=SchemeDataEditorCursor1.ObjectForPoint(X,Y,
    TSchemeVisual(VisualSender).Param);
  AEnabled:=p<>nil;
  if not AEnabled then exit;
  AEnabled:=(p.State=AObject.State);        //enable for equal objects states
end;

//---------------------- Custom Drawing ---------------------

procedure TFormMain.SchemeDataEditorCursor1ObjectPaint(Sender,
  VisualSender: TObject; AObject: TAbstractPaintObject; AZoom: Extended;
  ACanvas: TCanvas; AParam: Integer);
var t:TShapeType;
begin
  if (AParam=0)and(AObject is TPaintObjectShape) then
  with AObject as TPaintObjectShape do
  begin
    t:=ShapeType;
    ShapeType:=stCircle;
    Paint(AZoom,ACanvas,AParam);
    ShapeType:=t;
    exit;
  end;
  AObject.Paint(AZoom,ACanvas,AParam);
end;

procedure TFormMain.ActionResizedExecute(Sender: TObject);
begin //Resized on/off
  pSelectedObject.Resized:=not pSelectedObject.Resized;
  SchemeDataEditorCursor1.ObjectRepaintDirect(pSelectedObject);
end;

procedure TFormMain.ActionSelectedExecute(Sender: TObject);
begin //Selected on/off
  pSelectedObject.Selected:=not pSelectedObject.Selected;
  SchemeDataEditorCursor1.ObjectRepaintDirect(pSelectedObject);
end;

procedure TFormMain.SpinEdit3Change(Sender: TObject);
begin //Blink interval
  SchemeDataEditorCursor1.TimerInterval:=SpinEdit3.Value;
end;

procedure TFormMain.CheckBox3Click(Sender: TObject);
begin  //DefaultDrawing
  SchemeDataEditorCursor1.DefaultDrawing:=CheckBox3.Checked;
end;

procedure TFormMain.CheckBox4Click(Sender: TObject);
begin //Full drawing
  SchemeDataEditorCursor1.FullMovedDrawing:=CheckBox4.Checked;
end;


procedure TFormMain.ActionReloadExecute(Sender: TObject);
begin //Reload
  CreateAll;
end;

end.
