unit PumpFrm;
{
  (C) 2000 - 2001 Jindrich Jindrich, Pavel Pisa, PiKRON Ltd.

  Originators of the CHROMuLAN project:

  Jindrich Jindrich - http://www.jindrich.com
                      http://orgchem.natur.cuni.cz/Chromulan/
                      software developer, project coordinator
  Pavel Pisa        - http://cmp.felk.cvut.cz/~pisa
                      embeded software developer
  PiKRON Ltd.       - http://www.pikron.com
                      project initiator, sponsor, instrument developer

  The CHROMuLAN project is distributed under the GNU General Public Licence.
  See file COPYING for details.

  Originators reserve the right to use and publish sources
  under different conditions too. If third party contributors
  do not accept this condition, they can delete this statement
  and only GNU license will apply.
}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  RackCtls, ExtCtrls, UlanType, {v0.22}ULRecTyp, {/v0.22}
  ModuType, Modulu, ULDRObju, StdCtrls, Spin,
  MyType, PBSpinEdit, PBNumEdit;{msgu}

type
  TPumpForm = class(TForm)
    ScrewPanel: TScrewPanel;
    RunBtn: TLEDButton;
    HoldBtn: TLEDButton;
    EndBtn: TLEDButton;
    StartBtn: TLEDButton;
    PurgeBtn: TLEDButton;
    StopBtn: TLEDButton;
    ABtn: TLEDButton;
    BBtn: TLEDButton;
    CBtn: TLEDButton;
    Label1: TLabel;
    Label2: TLabel;
    PressureLEDDisplay: TLEDDisplay;
    Label3: TLabel;
    Label4: TLabel;
    AEdit: TSpinEdit;
    BEdit: TSpinEdit;
    CEdit: TSpinEdit;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    SolventHintPanel: TPanel;
    Label10: TLabel;
    XEdit: TEdit;
    Label11: TLabel;
    FlowEdit: TPBNumEdit;
    Press_LEdit: TPBNumEdit;
    Press_HEdit: TPBNumEdit;
    procedure StartBtnClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Press_LEditChange(Sender: TObject);
    procedure BEditChange(Sender: TObject);
    procedure ABtnClick(Sender: TObject);
    procedure BBtnClick(Sender: TObject);
    procedure CBtnClick(Sender: TObject);
    procedure XEditChange(Sender: TObject);
    procedure FlowEditChange(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FModule: TModule;
    IsInXChange: boolean;
    IsInBCChange: boolean;
  protected
    procedure SetModule(AModule: TModule);
  public
    { Public declarations }
    procedure UpdateGradValues(upload:boolean);
    property Module: TModule read FModule write SetModule;
    procedure WMAppMessage(var Msg:TMessage);message WM_APPMESSAGE;
    procedure GradModuleToEdits;
    procedure PressModuleToEdit;
  end;

var
  PumpForm: TPumpForm;

function PumpFrmEdit(AModule: pointer): integer;

implementation

{$R *.DFM}

const
  AConc = 100;
  BConc = 50;
  CConc = 0;

function XToBC(x: integer; var b: integer; var c: integer):boolean;
  { if the content of solvent X in resulting two component mixture
    should be x (%), and the three components of gradient contain:
    A = 100% X, B = 50% X, C = 0% X, this function returns how much
    of B, C (and A - calculated to 100%) should be mixed.
    Returns false if x is in invalid range. }
var
  a: integer;
begin
  Result := false;
  if (x < 0) or (x > 100) then
    exit;
  if x < BConc then begin
    b := 100 * x div (CConc + BConc);
    c := 100 * (BConc - x) div (CConc + BConc);
  end else begin
    a := 100 * (x - BConc) div (AConc - BConc);
    b := 100 * (AConc - x) div (AConc - BConc);
    c := 100 - (a + b);
  end;
  Result := true;
end;

function BCToX(b, c: integer; var x: integer): boolean;
var a: integer;
begin
  Result := false;
  a := 100 - b - c;
  if (b < 0) or (b > 100) or (c < 0) or (c > 100) or (a < 0) then
    exit;
  x := (a * AConc + b * BConc + c * CConc) div (a + b + c);
  Result := true;
end;

function PumpFrmEdit(AModule: pointer): integer;
var p: TPumpForm;
begin
{  TModule(AModule).DownloadPropVals;}
  p := TPumpForm.Create(Application);
  {PumpForm.Module := AModule;}
  p.Module := AModule;
  p.Show;
  Result := mrOK;
{  Result := PumpForm.ShowModal;}
end;

procedure TPumpForm.StartBtnClick(Sender: TObject);
begin
  if Sender is TLedButton then begin
    with Sender as TLedButton do begin
      case Tag of
        piStart, piStop, piPurge: Module.DoCommand(Tag);
      end;
    end;
  end;
end;

procedure TPumpForm.SetModule(AModule: TModule);

  procedure SetUpdates(OnOff:boolean);
  var p: TModuleProp;
  begin
    if FModule.FindProp(piPress, p) then begin
      if OnOff then
        p.UpdateInterval := 500
      else
        p.UpdateInterval := 0;
    end;
    if FModule.FindProp(piGrad_B, p) then begin
      if OnOff then
        p.UpdateInterval := 500
      else
        p.UpdateInterval := 0;
    end;
    if FModule.FindProp(piGrad_C, p) then begin
      if OnOff then
        p.UpdateInterval := 500
      else
        p.UpdateInterval := 0;
    end;
  end;

begin
  if FModule <> nil then begin
    FModule.ULDR.UserUnregister(Self);
    SetUpdates(false);
    FModule := nil;
  end;
  if AModule <> nil then begin
    FModule := AModule;
    {RunBtn: TLEDButton;
     HoldBtn: TLEDButton;
     EndBtn: TLEDButton;
     StartBtn: TLEDButton;
     PurgeBtn: TLEDButton;
     StopBtn: TLEDButton;
     ABtn: TLEDButton;
     BBtn: TLEDButton;
     CBtn: TLEDButton;}

    Press_HEdit.Value := StrToFloat(Module.UserValStr[piPress_H]);
    Press_LEdit.Value := StrToFloat(Module.UserValStr[piPress_L]);
    FlowEdit.Value := StrToFloat(Module.UserValStr[piFlow]);
    GradModuleToEdits;
    PressModuleToEdit;
    SetUpdates(true);
    FModule.ULDR.UserRegister(Self);
  end;
end;

procedure TPumpForm.PressModuleToEdit;
begin
  PressureLEDDisplay.Value := {round}(StrToFloat(Module.UserValStr[piPress]))
end;

procedure TPumpForm.GradModuleToEdits;
begin
  IsInBCChange := true;
  try
    BEdit.Value := Module.UserValInt[piGrad_B];
    CEdit.Value := Module.UserValInt[piGrad_C];
    UpdateGradValues(false);
  finally
    IsInBCChange := false;
  end;
end;

procedure TPumpForm.UpdateGradValues(upload:boolean);
var x: integer;
begin
  AEdit.Value := 100 - BEdit.Value - CEdit.Value;
  BEdit.MaxValue := 100 - CEdit.Value;
  CEdit.MaxValue := 100 - BEdit.Value;
  if IsInBCChange then begin
    if BCToX(BEdit.Value, CEdit.Value, x) then
      XEdit.Text := IntToStr(x);
  end;
  if upload then begin
    Module.UserValInt[piGrad_B] := BEdit.Value;
    Module.UserValInt[piGrad_C] := CEdit.Value;
  end;
end;

procedure TPumpForm.FormCreate(Sender: TObject);
begin
{  RunBtn: TLEDButton;
  HoldBtn: TLEDButton;
  EndBtn: TLEDButton;}
  StartBtn.Tag := piStart;
  PurgeBtn.Tag := piPurge;
  StopBtn.Tag := piStop;
{  ABtn: TLEDButton;
  BBtn: TLEDButton;
  CBtn: TLEDButton;
}
  Press_HEdit.Tag := piPress_H;
  Press_LEdit.Tag := piPress_L;
end;

procedure TPumpForm.Press_LEditChange(Sender: TObject);
begin
  if Sender is TSpinEdit then begin
    with Sender as TSpinEdit do begin
      Module.UserValInt[Tag] := Value;
    end;
  end;
end;

procedure TPumpForm.BEditChange(Sender: TObject);
begin
  if IsInXChange then
    exit;
  if IsInBCChange then
    exit;
  IsInBCChange := true;
  try
    UpdateGradValues(true);
  finally
    IsInBCChange := false;
  end;
end;

procedure TPumpForm.ABtnClick(Sender: TObject);
begin
  Module.UserValStr[piGradDir] := '0';
end;

procedure TPumpForm.BBtnClick(Sender: TObject);
begin
  Module.UserValStr[piGradDir] := '1';
end;

procedure TPumpForm.CBtnClick(Sender: TObject);
begin
  Module.UserValStr[piGradDir] := '2';
end;

procedure TPumpForm.XEditChange(Sender: TObject);
var code, x, b, c:integer;
begin
  if IsInXChange then
    exit;
  if IsInBCChange then
    exit;
  IsInXChange := true;
  try
    val(XEdit.Text, x, code);
    if code = 0 then begin
      if not XToBC(x, b, c) then
        exit;
      BEdit.MaxValue := b;
      BEdit.Value := b;
      CEdit.MaxValue := c;
      CEdit.Value := c;
      UpdateGradValues(true);
    end;
  finally
    IsInXChange := false;
  end;
end;

procedure TPumpForm.WMAppMessage(var Msg:TMessage);
begin
  case Msg.wParam of
    cmULObjUpdated: begin
      if TULDRObj(Msg.lParam) = FModule.ULDR then begin
        GradModuleToEdits;
        PressModuleToEdit;
      end;
    end;
  end;
end;


procedure TPumpForm.FlowEditChange(Sender: TObject);
begin
  if Module <> nil then
    Module.UserValStr[piFlow] := FloatToStr(FlowEdit.Value);
end;

procedure TPumpForm.FormDestroy(Sender: TObject);
begin
  Module := nil;
end;

end.
