unit VisZDVT;

interface

uses
{$ifdef VER150}
  DesignIntf, DesignEditors, DesignWindows, DsnConst,
{$else}
  DsgnIntf,
{$endif}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, stdctrls, ScadaBase;


type
  PVisZDVTDir =^TVisZDVTDir;
  TVisZDVTDir = record
    Name: string[32];
    ImageObj: TImage;
    FrameBlokObj: TShape;
    LabelObj: TLabel;
  end;

  TVisZDVT = class(TCustomScadaObject)
  private
    FData: TStringList;

    procedure SetupData(Value: TStringList);
    procedure LoadSetupData;
    procedure SaveSetupData;
  protected
    FImagePic1: TPicName; // открыто
    FImagePic2: TPicName; // закрыто
    FImagePic3: TPicName; // закрыто

    FTagControl: integer;
    FTagSost: integer;
    FTagBlok: integer;

    FCurSost: integer;
    FCurMode: integer;
    FCurBlok: integer;

    procedure SetImageSost(Value: integer);
    procedure SetFrameMode(Value: integer);
    procedure SetFrameBlok(Value: integer);
    procedure SetDirPicture(idx, value: integer);

    procedure Loaded; override;
  public
    TagName: TTagName;
    DeviceName: TDeviceName;
    ImagePic: TPicName;

    LabelObj: TLabel;
    FrameModeObj: TShape;

    DirCount: integer;
    Dir: array of PVisZDVTDir;

    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;

    procedure Init; override;
    procedure Process; override;

    procedure FrameUpdate;
    procedure FreeDirs;

  published
    property Data: TStringList read FData write SetupData;
  end;


  TVisZDVTEditor = class(TComponentEditor)
  private
  public
    procedure Edit; override;
  end;



procedure Register;

implementation
uses
  TagStorage,
  numbers,
  ExtDlgs,
  VisZDVTSetup,
  RpVisualUtils,
  RpVisualGlobal;

procedure Register;
begin
  RegisterComponents('Scada', [TVisZDVT]);
  RegisterComponentEditor(TVisZDVT, TVisZDVTEditor);
end;

{ TVisZDVT }

constructor TVisZDVT.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  FEraseBackground := true;
  Width := 100;
  Height := 100;
  ShowHint := true;

  FData := TStringList.Create;

  Dir := nil;
  DirCount := 0;

  // Создание рамки Mode
  FrameModeObj := TShape.Create(self);
  FrameModeObj.Parent := self;
  FrameModeObj.Visible := true;
  FrameModeObj.Brush.Style := bsClear;
  FrameModeObj.Pen.Color := clAqua;

  // Создание метки
  LabelObj := TLabel.Create(Self);
  LabelObj.Parent := self;
  LabelObj.Visible := true;
  LabelObj.Transparent := true;
  LabelObj.Font.Color := clWhite;
  LabelObj.Font.Size := 10;
  LabelObj.Font.Style := [fsBold];
  LabelObj.Font.Name := 'Tahoma';

  LabelObj.OnClick := OnDeviceClick;

  FTagControl := -1;
  FTagSost := -1;
  FTagBlok  := -1;

  FCurSost := -1;
  FCurMode := -1;
  FCurBlok := -1;
end;

destructor TVisZDVT.Destroy;
begin
  FreeDirs;
  inherited;
end;

procedure TVisZDVT.SetupData(Value: TStringList);
begin
  FData.Assign(Value);
  LoadSetupData;
end;


procedure TVisZDVT.SetImageSost(Value: integer);
var
  i,k,alm: integer;
begin
  if (Value <> FCurSost) and (Value>=0) then try

    k := Value and $7F;
    alm := iif(k=Value, 0, 1);
    dec(k);

    for i:=0 to DirCount-1 do
      SetDirPicture(i, iif(i=k, 1+alm, 0));
    FCurSost := Value;
  except
    LabelObj.Caption := 'PIC';
  end;
end;

procedure TVisZDVT.SetFrameMode(Value: integer);
begin
  if (Value <> FCurMode) then begin
    if (value) > 0 then
      FrameModeObj.Pen.Color := clAqua
    else
      FrameModeObj.Pen.Color := Color;
    FCurMode := Value;
  end;
end;

procedure TVisZDVT.SetFrameBlok(Value: integer);
var
  i: integer;
begin
  if (Value <> FCurBlok) then begin
    if (value) > 0 then
      for i:=0 to DirCount-1 do Dir[i].FrameBlokObj.Pen.Color := clYellow
    else
      for i:=0 to DirCount-1 do Dir[i].FrameBlokObj.Pen.Color := Color;
    FCurBlok := Value;
  end;
end;

procedure TVisZDVT.SetDirPicture(idx, value: integer);
begin
  case Value of
    0:Dir[idx].ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic1);
    1:Dir[idx].ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic2);
  else
    Dir[idx].ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic3);
  end;
end;


// INIT
procedure TVisZDVT.Init;
var
  _tagname: string;
begin
  inherited;

  _tagname := repl(TagName, TagIdRoot, TagRoot);

  IsConnectionBad := false;
  FTagControl := GetTagIndex(TagPath + '.ZDVT_' + _TagName + '_Control');
  FTagSost := GetTagIndex(TagPath + '.ZDVT_' + _TagName + '_Sost');
  FTagBlok := GetTagIndex(TagPath + '.ZDVT_' + _TagName + '_Blok');
  IsConnectionBad := (FTagControl<0) or (FTagSost<0) or (FTagBlok<0);
end;

// PROCESS HANDLER
procedure TVisZDVT.Process;
var
  value: integer;
begin
  IsValueBad := false;

  value := GetTagValue(FTagSost);
  SetImageSost(value);
  IsValueBad := IsValueBad or (value < 0);

  value := GetTagValue(FTagControl);
  SetFrameMode(value);
  IsValueBad := IsValueBad or (value < 0);

  value := GetTagValue(FTagBlok);
  SetFrameBlok(value);
  IsValueBad := IsValueBad or (value < 0);
  inherited;
end;



procedure TVisZDVT.LoadSetupData;
var
  s, s1, s2: string;
  k, i, j, v: integer;
  img_xs, img_ys, frm_xo, frm_yo, frm_xs, frm_ys, lab_xo, lab_yo: integer;
begin

  // TagPath
  if FData.Count>0 then s := FData.Strings[0] else s := '';
  k := pos('.', s);
  TagPath := copy(s, 1, k-1);

  // TagName
  delete(s, 1, k); k := pos(';', s);
  TagName := copy(s, 1, k-1);

  // DeviceName
  delete(s, 1, k);
  DeviceName := trim(s);
  Hint := DeviceName;


  // Image size
  if FData.Count>1 then s := FData.Strings[1] else s := '';
  k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  img_xs := v;

  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  img_ys := v;

  // BlokFrame offset
  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  frm_xo := v;

  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  frm_yo := v;

  // BlokFrame size
  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  frm_xs := v;

  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  frm_ys := v;

  // Label offset
  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  lab_xo := v;

  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  lab_yo := v;

  // Pic name
  delete(s, 1, k);
  ImagePic := trim(s);

  // Label
  if FData.Count>2 then s := FData.Strings[2] else s := '';
  k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  LabelObj.Left := v;

  delete(s, 1, k); k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  LabelObj.Top := v;

  delete(s, 1, k);
  LabelObj.Caption := trim(s);

  // Обновление рамок
  FrameUpdate;

  // Загрузка направлений
  FreeDirs;
  if FData.Count>3 then s := FData.Strings[3] else s := '';
  val(s, v, j);
  DirCount := v;
  SetLength(Dir, DirCount);

  for i:=0 to DirCount-1 do begin
    new( Dir[i] );
    Dir[i].ImageObj := TImage.Create(Self);
    Dir[i].ImageObj.Parent := self;
    Dir[i].ImageObj.Visible := true;
    Dir[i].ImageObj.Stretch := true;
    Dir[i].ImageObj.OnClick := OnDeviceClick;
    Dir[i].ImageObj.Width := img_xs;
    Dir[i].ImageObj.Height := img_ys;

    Dir[i].FrameBlokObj := TShape.Create(Self);
    Dir[i].FrameBlokObj.Parent := self;
    Dir[i].FrameBlokObj.Visible := true;
    Dir[i].FrameBlokObj.Pen.Color := clYellow;
    Dir[i].FrameBlokObj.Brush.Style := bsClear;
    Dir[i].FrameBlokObj.OnMouseUp := OnDeviceMouseUp;
    Dir[i].FrameBlokObj.Width := frm_xs;
    Dir[i].FrameBlokObj.Height := frm_ys;

    Dir[i].LabelObj := TLabel.Create(Self);
    Dir[i].LabelObj.Parent := self;
    Dir[i].LabelObj.Transparent := true;
    Dir[i].LabelObj.Visible := true;
    Dir[i].LabelObj.Font.Name := 'Courier New';
    Dir[i].LabelObj.Font.Size := 7;
    Dir[i].LabelObj.Font.Color := clMenu;
    Dir[i].LabelObj.OnMouseUp := OnDeviceMouseUp;

    if FData.Count>4+i then s := FData.Strings[4+i] else s := '';
    k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Dir[i].ImageObj.Left := v;
    Dir[i].FrameBlokObj.Left := frm_xo + v;
    Dir[i].LabelObj.Left := lab_xo + v;

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Dir[i].ImageObj.Top := v;
    Dir[i].FrameBlokObj.Top := frm_yo + v;
    Dir[i].LabelObj.Top := lab_yo + v;

    delete(s, 1, k); k := pos(',', s);
    Dir[i].LabelObj.Caption := copy(s, 1, k-1);

    delete(s, 1, k);
    Dir[i].Name := trim(s);

    s := VisImagesPath + ImagePic;
    try
      if FileExists(s) then Dir[i].ImageObj.Picture.LoadFromFile(s);
    except
    end;
  end;

  // имена картинок
  s2 := ImagePic;
  i := pos('_',s2);
  s1 := copy(s2, 1, i);
  delete(s2, 1, i+1);

  FImagePic1 := s1 + '1' + s2;
  FImagePic2 := s1 + '2' + s2;
  FImagePic3 := s1 + '3' + s2;
end;

procedure TVisZDVT.SaveSetupData;
var
  i: integer;
begin
  FData.Clear;
  FData.Add( TagPath + '.' + TagName + ';' + DeviceName );

  if DirCount=0 then
    FData.Add( format('0,0,0,0,0,0,0,0,%s', [ImagePic]) )
  else
    FData.Add( format('%d,%d,%d,%d,%d,%d,%d,%d,%s', [
        Dir[0].ImageObj.Width,
        Dir[0].ImageObj.Height,
        Dir[0].FrameBlokObj.Left-Dir[0].ImageObj.Left,
        Dir[0].FrameBlokObj.Top-Dir[0].ImageObj.Top,
        Dir[0].FrameBlokObj.Width,
        Dir[0].FrameBlokObj.Height,
        Dir[0].LabelObj.Left-Dir[0].ImageObj.Left,
        Dir[0].LabelObj.Top-Dir[0].ImageObj.Top,
        ImagePic]) );

  FData.Add( format('%d,%d,%s', [LabelObj.Left, LabelObj.Top, LabelObj.Caption]) );

  FData.Add(IntToStr(DirCount));
  for i:=0 to DirCount-1 do
    FData.Add( format('%d,%d,%s,%s', [
        Dir[i].ImageObj.Left, Dir[i].ImageObj.Top,
        Dir[i].LabelObj.Caption,
        Dir[i].Name
        ]));
end;


procedure TVisZDVT.Loaded;
begin
  inherited;
  LoadSetupData;
end;


procedure TVisZDVT.FrameUpdate;
begin
  FrameModeObj.Left   := LabelObj.Left   - ModeMarginX;
  FrameModeObj.Top    := LabelObj.Top    - ModeMarginY;
  FrameModeObj.Width  := LabelObj.Width  + 2*ModeMarginX;
  FrameModeObj.Height := LabelObj.Height + 2*ModeMarginY;
end;

procedure TVisZDVT.FreeDirs;
var
  i: integer;
begin
  for i:=0 to DirCount-1 do begin
    Dir[i].ImageObj.Free;
    Dir[i].FrameBlokObj.Free;
    Dir[i].LabelObj.Free;
    Dispose(Dir[i]);
  end;
  Dir := nil;
end;



{ TVisZDVTEditor }

procedure TVisZDVTEditor.Edit;
begin
  inherited;
  VisZDVTSetupForm := TVisZDVTSetupForm.Create(nil);

  VisZDVTSetupForm.M := Component as TVisZDVT;
  VisZDVTSetupForm.D := Self;
  if VisZDVTSetupForm.ShowModal = mrOk then
    VisZDVTSetupForm.M.SaveSetupData
  else
    VisZDVTSetupForm.M.LoadSetupData;

  VisZDVTSetupForm.Free;
end;


end.
