unit VisVespC;

interface

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


type
  TVisVespC = class(TCustomScadaObject)
  private
    FData: TStringList;

    FImagePic1: TPicName;
    FImagePic2: TPicName;
    FImagePic3: TPicName;
    FImagePic4: TPicName;

    procedure SetupData(Value: TStringList);
    procedure LoadSetupData;
    procedure SaveSetupData;
  protected
    FTagVspcEnable: integer;
    FTagVspcReg10: integer;
    FTagVspcAnswer: integer;
    FTagVspcErrorFlag: integer;

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

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

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

    ImageObj: TImage;
    LabelObj: TLabel;
    FrameModeObj: TShape;
    FrameBlokObj: TShape;

    DatCount: integer;
    Datchik: array of PVisMachineDat;

    OpFreqMax: integer;

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

    procedure Init; override;
    procedure Process; override;

    procedure FrameUpdate;
    procedure FreeDatchiks;

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

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



procedure Register;

implementation
uses
  TagStorage,
  numbers,
  ExtDlgs,
  VisVespCSetup,
  RpVisualGlobal,
  RpVisualLegacyPanels,
  RpVisualUtils,
  RpVisualMain;

procedure Register;
begin
  RegisterComponents('Scada', [TVisVespC]);
  RegisterComponentEditor(TVisVespC, TVisVespCEditor);
end;

{ TVisVespC }

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

  FData := TStringList.Create;

  Datchik := nil;
  DatCount := 0;

  // Создание изображения
  ImageObj := TImage.Create(Self);
  ImageObj.Parent := self;
  ImageObj.Stretch := true;
  ImageObj.Visible := true;

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

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

  // Создание метки
  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';

  ImageObj.OnClick := OnDeviceClick;
  LabelObj.OnClick := OnDeviceClick;

  FTagVspcEnable := -1;
  FTagVspcReg10 := -1;
  FTagVspcAnswer := -1;
  FTagVspcErrorFlag := -1;

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

destructor TVisVespC.Destroy;
begin
  FreeDatchiks;
  inherited;
end;

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


procedure TVisVespC.SetImageSost(Value: integer);
begin
  if (Value <> FCurSost) and (Value>=0) then try
    case value of
      0:   ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic1);
      1:   ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic2);
      2:   ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic3);
    else
      ImageObj.Picture.LoadFromFile(VisImagesPath + FImagePic4);
    end;
    FCurSost := Value;
  except
    LabelObj.Caption := 'PIC';
  end;
end;

procedure TVisVespC.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 TVisVespC.SetFrameBlok(Value: integer);
begin
  if (Value <> FCurBlok) then begin
    if (value) > 0 then
      FrameBlokObj.Pen.Color := clYellow
    else
      FrameBlokObj.Pen.Color := Color;
    FCurBlok := Value;
  end;
end;

procedure TVisVespC.SetDatColor(idx, value: integer);
begin
  if (value <> Datchik[idx].valSost) or (value>0) then begin

    if Datchik[idx].ColorScheme = 0 then begin
      case value of
      0: Datchik[idx].Shape.Brush.Color := clAqua;

      1: Datchik[idx].Shape.Brush.Color := clYellow;

      2: Datchik[idx].Shape.Brush.Color := clRed;

      3: if Datchik[idx].Shape.Brush.Color = clRed then
           Datchik[idx].Shape.Brush.Color := clYellow
         else
           Datchik[idx].Shape.Brush.Color := clRed;
      end;
    end;

    if Datchik[idx].ColorScheme = 1 then begin
      if value = 0 then
        Datchik[idx].Shape.Brush.Color := clAqua
      else
        Datchik[idx].Shape.Brush.Color := clYellow;
    end;

    Datchik[idx].valSost := value;
  end;

end;


// INIT
procedure TVisVespC.Init;
var
  i: integer;
  _tagname: string;
begin
  inherited;
  _tagname := repl(TagName, TagIdRoot, TagRoot);



  FTagVspcEnable := GetTagIndex(TagPath + '.VSPC_' + _TagName + '_Enable');
  FTagVspcReg10 := GetTagIndex(TagPath + '.VSPC_' + _TagName + '_Reg10');
  FTagVspcAnswer := GetTagIndex(TagPath + '.VSPC_' + _TagName + '_Answer');
  FTagVspcErrorFlag := GetTagIndex(TagPath + '.VSPC_' + _TagName + '_ErrorFlag');

  IsConnectionBad := (FTagVspcEnable<0) or (FTagVspcReg10<0) or
      (FTagVspcAnswer<0) or (FTagVspcErrorFlag<0);

  for i:=0 to DatCount-1 do with Datchik[i]^ do begin
    TagIdxOutput := GetTagIndex(format('%s.RKSV_%s%s_Output',
        [TagPath, _TagName, TagPostfix]));

    TagIdxAlarm := GetTagIndex(format('%s.RKSV_%s%s_Alarm',
        [TagPath, _TagName, TagPostfix]));

    TagIdxBlok := GetTagIndex(format('%s.RKSV_%s%s_Blok',
        [TagPath, _TagName, TagPostfix]));

    IsConnectionBad := (IsConnectionBad) or (TagIdxOutput<0) or
        (TagIdxAlarm<0) or (TagIdxBlok<0);
  end;

end;

// PROCESS HANDLER
procedure TVisVespC.Process;
var
  value, venab, vreg10, verr, vansw, valOutput, valAalarm, blokval, i: integer;
begin

  IsValueBad := false;

  venab := GetTagValue(FTagVspcEnable);
  vreg10 := GetTagValue(FTagVspcReg10);
  vansw := GetTagValue(FTagVspcAnswer);
  verr := GetTagValue(FTagVspcErrorFlag);


  IsValueBad := IsValueBad or (venab < 0) or (vreg10 < 0) or (vansw < 0) or (verr < 0);

  vreg10 := vreg10 and $FF;
  if ((vreg10 and $C0) > 0) or (verr>0) then value := 2 else
  if (vreg10 and $11) = $11 then value := 1 else
  if (vreg10 and 2) > 0 then value:=0 else value:=3;
  SetImageSost(value);

  SetFrameMode( (venab and 2) );

  blokval := 0;
  for i:=0 to DatCount-1 do begin
    valOutput := GetTagValue(Datchik[i].TagIdxOutput);
    valAalarm := GetTagValue(Datchik[i].TagIdxAlarm);
    value := GetTagValue(Datchik[i].TagIdxBlok);
    IsValueBad := IsValueBad or (valOutput < 0) or (valAalarm < 0) or (value < 0);
    blokval := blokval or value;

    SetDatColor(i, valOutput * 2 + valAalarm);
  end;
  SetFrameBlok(blokval);

  inherited;

end;



procedure TVisVespC.LoadSetupData;
var
  s, s1, s2: string;
  k, i, j, v: 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
  if FData.Count>1 then s := FData.Strings[1] else s := '';
  k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  ImageObj.Left := v;

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

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

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

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

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


  // 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;

  // Загрузка датчиков
  FreeDatchiks;
  if FData.Count>3 then s := FData.Strings[3] else s := '';
  k := pos(',', s);
  val(copy(s, 1, k-1), v, j);
  DatCount := v;
  SetLength(Datchik, DatCount);

  delete(s, 1, k);
  val(s, v, j);
  OpFreqMax := v;

  for i:=0 to DatCount-1 do begin
    new( Datchik[i] );
    Datchik[i].Shape := TShape.Create(Self);
    Datchik[i].Shape.Parent := self;
    Datchik[i].Shape.Visible := true;
    Datchik[i].Shape.Brush.Color := clAqua;
    Datchik[i].Shape.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);
    Datchik[i].Shape.Left := v;

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Datchik[i].Shape.Top := v;

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Datchik[i].Shape.Width := v;

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Datchik[i].Shape.Height := v;

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Datchik[i].Shape.Shape := TShapeType(v);

    delete(s, 1, k); k := pos(',', s);
    val(copy(s, 1, k-1), v, j);
    Datchik[i].ColorScheme := v;

    delete(s, 1, k); k := pos(',', s);
    Datchik[i].TagPostfix := copy(s, 1, k-1);

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

    Datchik[i].TagIdxOutput := -1;
    Datchik[i].TagIdxAlarm := -1;
    Datchik[i].TagIdxBlok := -1;

    Datchik[i].valSost := -1;

  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;
  FImagePic4 := s1 + '4' + s2;

end;

procedure TVisVespC.SaveSetupData;
var
  i: integer;
begin
  FData.Clear;
  FData.Add( TagPath + '.' + TagName + ';' + DeviceName );
  FData.Add( format('%d,%d,%d,%d,%s', [
      ImageObj.Left, ImageObj.Top, ImageObj.Width, ImageObj.Height, ImagePic]) );
  FData.Add( format('%d,%d,%s', [LabelObj.Left, LabelObj.Top, LabelObj.Caption]) );

  FData.Add(IntToStr(DatCount) + ',' + IntToStr(OpFreqMax));
  for i:=0 to DatCount-1 do
    FData.Add( format('%d,%d,%d,%d,%d,%d,%s,%s', [
        Datchik[i].Shape.Left, Datchik[i].Shape.Top,
        Datchik[i].Shape.Width, Datchik[i].Shape.Height,
        ord(Datchik[i].Shape.Shape), Datchik[i].ColorScheme,
        Datchik[i].TagPostfix, Datchik[i].Name
        ]));

end;


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


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

  FrameBlokObj.Left   := LabelObj.Left   - BlokMarginX;
  FrameBlokObj.Top    := LabelObj.Top    - BlokMarginY;
  FrameBlokObj.Width  := LabelObj.Width  + 2*BlokMarginX;
  FrameBlokObj.Height := LabelObj.Height + 2*BlokMarginY;
end;

procedure TVisVespC.FreeDatchiks;
var
  i: integer;
begin
  for i:=0 to DatCount-1 do begin
    Datchik[i].Shape.Free;
    Dispose(Datchik[i]);
  end;
  Datchik := nil;
end;



{ TVisVespCEditor }

procedure TVisVespCEditor.Edit;
begin
  inherited;

  VisVespCSetupForm := TVisVespCSetupForm.Create(nil);

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

  VisVespCSetupForm.Free;

end;



end.
