unit DalCtrl;
{ Put on form then assign Control on the form (TEdit probably),
  to which detected TouchID should be assigned }
interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExeLogu,
  DalType, DalUtl;

type
  TOnTouchIDChange = procedure(const ATouchID: TTouchID) of object;

  TDalCtrl = class(TComponent)
  private
    { Private declarations }
    FControl: TControl;
    FTouchID: TTouchID;
      { last touch id Assigned }
    FLogFileName: TFileName;
      { to what file should be all touchids set to
        this control logged (one TouchIDStr - one line) }
    FExeLog: TExeLog;
    FOnChange: TOnTouchIDChange;
    FLogMemo: TMemo;
    function GetLogActive: boolean;
    procedure SetLogActive(OnOff: boolean);
    procedure SetLogFileName(const ALogFileName: TFileName);
    procedure SetTouchIDStr(const ATouchIDStr: TTouchIDStr);
    function GetTouchIDStr: TTouchIDStr;
  protected
    { Protected declarations }
    procedure Loaded; override;
    procedure Log(const msg:string);
    procedure SetTouchID(const ATouchID: TTouchID);
      { called through DalCtrls from module/ reader to
        inform all controls about the touch }
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); reintroduce;
    destructor Destroy; override;
    property TouchID: TTouchID read FTouchID write SetTouchID;
      { Every assignent to this property will update Control
        and eventually Log the TouchIDStr }
    property TouchIDStr: TTouchIDStr read GetTouchIDStr write SetTouchIDStr;
    property TheLog: TExeLog read FExeLog;
  published
    { Published declarations }
    property Control: TControl read FControl write FControl;
    property LogFileName: TFileName read FLogFileName write SetLogFileName;
    property LogActive: boolean read GetLogActive write SetLogActive;
    property LogMemo: TMemo read FLogMemo write FLogMemo;
    property OnChange: TOnTouchIDChange read FOnChange write FOnChange;
  end;

  TDalCtrls = class(TList)
    procedure Register(ADalCtrl: TDalCtrl);
    procedure Unregister(ADalCtrl: TDalCtrl);
    procedure TouchIDDetected(const ATouchID: TTouchID);
  end;

procedure Register;

function DalCtrls: TDalCtrls;

implementation
const
  FDalCtrls: TDalCtrls = nil;

function DalCtrls: TDalCtrls;
begin
  if FDalCtrls = nil then
    FDalCtrls := TDalCtrls.Create;
  Result := FDalCtrls;
end;
{TDalCtrls}
procedure TDalCtrls.Register(ADalCtrl: TDalCtrl);
begin
  if IndexOf(ADalCtrl) < 0 then
    Add(ADalCtrl);
end;

procedure TDalCtrls.Unregister(ADalCtrl: TDalCtrl);
var i: integer;
begin
  i := IndexOf(ADalCtrl);
  if i >= 0 then
    Delete(i);
end;

procedure TDalCtrls.TouchIDDetected(const ATouchID: TTouchID);
var i: integer;
begin
  for i := 0 to Count - 1 do
    TDalCtrl(Items[i]).SetTouchID(ATouchID);
end;
{/TDalCtrls}

{ Public declarations }
constructor TDalCtrl.Create(AOwner: TComponent);
begin
  inherited;
  DalCtrls.Register(Self);
end;

procedure TDalCtrl.Loaded;
begin
  inherited;
  DalCtrls.Register(Self);
end;

procedure TDalCtrl.Log(const msg: string);
begin
  if FExeLog <> nil then
    FExeLog.Log(msg);
  if FLogMemo <> nil then
    FLogMemo.Lines.Add(msg);
end;

destructor TDalCtrl.Destroy;
begin
  DalCtrls.Unregister(Self);
  FExeLog.Free;
  inherited;
end;

procedure TDalCtrl.SetTouchID(const ATouchID: TTouchID);
var
  s: TTouchIDStr;
  c:array[0..TouchIDStrLen] of char;
begin
  if TouchIDCmp(FTouchID, ATouchID) = 0 then
    exit;
  FTouchID := ATouchID;{dalutl}
  if IsEmptyTouchID(FTouchID) then
    exit;
  if Assigned(FOnChange) then
    FOnChange(FTouchID);
  s := dalutl.GetTouchIDStr(ATouchID);
  if FControl is TEdit then begin
    TEdit(FControl).Text := s;
  end else if FControl is TWinControl then begin
    SendMessage(TWinControl(FControl).Handle, WM_SETTEXT, 0, integer(StrPCopy(c, s)));
    {FControl.Caption := s;}
  end;
  Log(s);
end;

procedure TDalCtrl.SetTouchIDStr(const ATouchIDStr: TTouchIDStr);
var
  t: TTouchID;
begin
  dalutl.SetTouchIDStr(ATouchIDStr, t);
  TouchID := t;
end;

function TDalCtrl.GetTouchIDStr: TTouchIDStr;
begin
  Result := dalutl.GetTouchIDStr(FTouchID);
end;

function TDalCtrl.GetLogActive: boolean;
begin
  Result := (FExeLog <> nil) and (FExeLog.Active);
end;

procedure TDalCtrl.SetLogActive(OnOff: boolean);
begin
  if LogActive = OnOff then
    exit;
  if not OnOff then begin
    if FExeLog <> nil then
      FExeLog.Free;
    FExeLog := nil;
  end else begin
    if FLogFileName <> '' then begin
      FExeLog := TExeLog.Create(Self, FLogFileName);
      FExeLog.Name := Name + 'Log';
      FExeLog.NoHead := true;
      FExeLog.NoFoot := true;{ exelogu }
      FExeLog.Active := true;
    end;
  end;
end;

procedure TDalCtrl.SetLogFileName(const ALogFileName: TFileName);
var a: boolean;
begin
  if ALogFileName = FLogFileName then
    exit;
  a := LogActive;
  if a then
    LogActive := false;
  FLogFileName := ALogFileName;
  LogActive := a;
end;

procedure Register;
begin
  RegisterComponents('APP', [TDalCtrl]);
end;

initialization

finalization
  FDalCtrls.Free;
  FDalCtrls := nil;
end.
