unit UnitConfMaFrm;

{$mode objfpc}{$H+}

interface

uses
    {$IFDEF WINDOWS}Windows,{$ENDIF}
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  Menus, ExtCtrls, StdCtrls, Grids, ComCtrls, Buttons, MaskEdit, CheckLst,
  MolDraw, UnitClsTbl, UnitProcConfMaForm;

type

  { TConfMaFrm }

  TConfMaFrm = class(TForm)
    BitBtnFirst: TBitBtn;
    BitBtnGoTo: TBitBtn;
    BitBtnLast: TBitBtn;
    BitBtnLeft: TBitBtn;
    BitBtnRight: TBitBtn;
    BtnLaunch: TButton;
    BtSDFSel: TButton;
    BtQuit: TButton;
    BtMClear: TButton;
    BtPrevMod: TButton;
    BtNextMod: TButton;
    BtSDFSel1: TButton;
    BtVote: TButton;
    CLBMdls: TCheckListBox;
    EdtSDF: TEdit;
    EdtSDF1: TEdit;
    LabelCell: TLabel;
    LabelRefE: TLabel;
    LabelRefP: TLabel;
    LabelTitleM: TLabel;
    MaskEditGoto: TMaskEdit;
    MemoC: TMemo;
    OpenDialogSDF: TOpenDialog;
    OpenDialogSDF1: TOpenDialog;
    PanelMOL: TPanel;
    PanelMatrix: TPanel;
    Mol2DViewC       : TMol2DView;
    StringGridFragCmp: TStringGrid;
    procedure BtMClearClick(Sender: TObject);
    procedure BtNextModClick(Sender: TObject);
    procedure BtnLaunchClick(Sender: TObject);
    procedure BtPrevModClick(Sender: TObject);
    procedure BtQuitClick(Sender: TObject);
    procedure BtSDFSelClick(Sender: TObject);
    procedure BtSDFSel1Click(Sender: TObject);
    procedure BtVoteClick(Sender: TObject);
    procedure CLBMdlsClick(Sender: TObject);
    procedure CLBMdlsItemClick(Sender: TObject; Index: integer);
    procedure CLBMdlsKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState
      );
    procedure CLBMdlsKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure StringGridFragCmpDrawCell(Sender: TObject; aCol, aRow: Integer;
      aRect: TRect; aState: TGridDrawState);
    procedure StringGridFragCmpMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure ClearGrid;
    procedure BitBtnFirstClick(Sender: TObject);
    procedure BitBtnLastClick(Sender: TObject);
    procedure BitBtnLeftClick(Sender: TObject);
    procedure BitBtnRightClick(Sender: TObject);
    procedure BitBtnGoToClick(Sender: TObject);
    procedure MenuClearMemoClick(Sender: TObject);
    procedure PredUpdate;
  private
    { private declarations }
  public
    { public declarations }
  end; 

var
   ConfMaFrm: TConfMaFrm;
   clstbl: TClsTbl;
   SDFFile      : TStringList;
   SDFFileReady : boolean;
   expField,predField: string;
   selCol, selRow: integer;

implementation

{ TConfMaFrm }

//______________________________________________________________________________
//
//  StringGridFragCmpDrawCell
//______________________________________________________________________________
procedure TConfMaFrm.StringGridFragCmpDrawCell(Sender: TObject; aCol,
  aRow: Integer; aRect: TRect; aState: TGridDrawState);
var
   i, j, m : Integer;
begin
     with Sender as TStringGrid do begin
          // selected cell
          m:=RowCount-2;
          for j:=1 to m do begin
              for i:=1 to m do begin
                  if (ACol=j) and (ARow=i) then begin
                     if (j=selCol) and (i=selRow) then begin
                        Canvas.Brush.Color := clWhite;
                        Canvas.FillRect(aRect);
                        Canvas.Font.Color := clRed;
                        Canvas.Font.Style := [fsBold];
                     end;
                  end;
              end;
          end;
          // exp. TOTAL sums
          i := RowCount-1;
          for j:=1 to ColCount-1 do begin
              if (ACol=j) and (ARow=i) then begin
                 Canvas.Brush.Color := clBlue;
                 Canvas.FillRect(aRect);
                 Canvas.Font.Color := clWhite;
                 Canvas.Font.Style := [fsBold];
              end;
          end;
          // pred. TOTAL sums
          i := ColCount-1;
          for j:=1 to RowCount-1 do begin
              if (ACol=i) and (ARow=j) then begin
                 Canvas.Brush.Color := clBlue;
                 Canvas.FillRect(aRect);
                 Canvas.Font.Color := clWhite;
                 Canvas.Font.Style := [fsBold];
              end;
          end;
     end;
end;  // StringGridFragCmpDrawCell

//______________________________________________________________________________
//
//  StringGridFragCmpMouseDown
//______________________________________________________________________________
procedure TConfMaFrm.StringGridFragCmpMouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
var
   Col, Row : Integer;
   k: integer;
   PClsD: PTClsData;
begin
     StringGridFragCmp.MouseToCell(X, Y, Col, Row);  ///
     if Button=mbLeft then begin
        if (((Col-1)>=0) and ((Col-1)<clstbl.NCls))then begin
           if ((Row-1)=-1) then begin
              k:=clstbl.CurrE;
              clstbl.CurrE:=Col-1;
              ShowCellsStats(MemoC,clstbl);
              clstbl.CurrE:=k;
           end else if ((clstbl.SetCurrM(Col-1,Row-1)) and ((Row-1)<clstbl.NCls+1)) then begin
               PClsD:=clstbl.Items[clstbl.CurrM];
               Mol2DViewC.ShowMOL(PClsD^.Id);
               LabelMol(LabelCell,PClsD,clstbl);
               MaskEditGoto.Text:=IntToStr(PClsD^.Id);
           end;
        end;
     end;
     StringGridFragCmp.Repaint;
     //Compute statistics and display in MemoC
end;  // StringGridFragCmpMouseDown

//______________________________________________________________________________
//
//  ClearGrid
//______________________________________________________________________________
procedure TConfMaFrm.ClearGrid;
var
   m    : Integer;
   iCol : Integer;
   iRow : Integer;
begin
     m := 3;
     StringGridFragCmp.RowCount := m+1;
     StringGridFragCmp.ColCount := m+1;
     for iRow:=0 to m do begin
         for iCol:=0 to m do begin
             if ((iRow<>0) or (iCol<>0)) then
                StringGridFragCmp.Cells[iCol, iRow] := '';
         end;
     end;
     clstbl.ClsStat.ExpOld:=-1;
end;  // ClearGrid

//______________________________________________________________________________
//
//  BitBtnFirstClick
//______________________________________________________________________________
procedure TConfMaFrm.BitBtnFirstClick(Sender: TObject);
var
   PClsD: PTClsData;
begin
     if (clstbl.FirstCurrM) then begin
        PClsD:=clstbl.Items[clstbl.CurrM];
        Mol2DViewC.ShowMOL(PClsD^.Id);
        LabelMol(LabelCell,PClsD,clstbl);
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
     end;
end;  // BitBtnFirstClick

//______________________________________________________________________________
//
//  BitBtnLastClick
//______________________________________________________________________________
procedure TConfMaFrm.BitBtnLastClick(Sender: TObject);
var
   PClsD: PTClsData;
begin
     if (clstbl.LastCurrM) then begin
        PClsD:=clstbl.Items[clstbl.CurrM];
        Mol2DViewC.ShowMOL(PClsD^.Id);
        LabelMol(LabelCell,PClsD,clstbl);
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
     end;
end;  // BitBtnLastClick

//______________________________________________________________________________
//
//  BitBtnLeftClick
//______________________________________________________________________________
procedure TConfMaFrm.BitBtnLeftClick(Sender: TObject);
var
   PClsD: PTClsData;
begin
     if (clstbl.PrevCurrM) then begin
        PClsD:=clstbl.Items[clstbl.CurrM];
        Mol2DViewC.ShowMOL(PClsD^.Id);
        LabelMol(LabelCell,PClsD,clstbl);
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
     end;
end;  // BitBtnLeftClick

//______________________________________________________________________________
//
//  BitBtnRightClick
//______________________________________________________________________________
procedure TConfMaFrm.BitBtnRightClick(Sender: TObject);
var
   PClsD: PTClsData;
begin
     if (clstbl.NextCurrM) then begin
        PClsD:=clstbl.Items[clstbl.CurrM];
        Mol2DViewC.ShowMOL(PClsD^.Id);
        LabelMol(LabelCell,PClsD,clstbl);
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
     end;
end;  // BitBtnRightClick

//______________________________________________________________________________
//
//  BitBtnGoToClick
//______________________________________________________________________________
procedure TConfMaFrm.BitBtnGoToClick(Sender: TObject);
var
   i,k    : Integer;
   Code : Integer;
   PClsD: PTClsData;
begin
     Val(MaskEditGoto.Text, i, Code);
     if Code=0 then begin
        k:=clstbl.CurrM;
        clstbl.CurrM:=0;
        PClsD:=PTClsData(clstbl.Items[clstbl.CurrM]);
        while ((clstbl.CurrM<clstbl.Count) and (PClsD^.Id<>i)) do begin
              PClsD:=PTClsData(clstbl.Items[clstbl.CurrM]);
              clstbl.CurrM:=clstbl.CurrM+1;
        end;
        if (PClsD^.Id=i) then begin
           clstbl.CurrE:=PClsD^.Exp;
           clstbl.CurrP:=PClsD^.Preds[PClsD^.PredID];
           Mol2DViewC.ShowMOL(PClsD^.Id);
           LabelMol(LabelCell,PClsD,clstbl);
        end else begin
            clstbl.CurrM:=k;
            PClsD:=PTClsData(clstbl.Items[clstbl.CurrM]);
            clstbl.CurrE:=PClsD^.Exp;
            clstbl.CurrP:=PClsD^.Preds[PClsD^.PredID];
        end;
     end;
end;  // BitBtnGoToClick


//______________________________________________________________________________
//
//   MenuClearMemoClick
//______________________________________________________________________________
procedure TConfMaFrm.MenuClearMemoClick(Sender: TObject);
begin
     MemoC.Clear;
end;  // MenuClearMemoClick

procedure TConfMaFrm.PredUpdate;
var
   PClsD: PTClsData;
   tmpSL: TStringList;
begin
     if (clstbl.GotoPred(CLBMdls.ItemIndex)) then begin
        MemoC.Clear;
        Welcome(MemoC);
        ClearGrid;
        LoadGrid(StringGridFragCmp, clstbl);
        tmpSL:=clstbl.ClsStat.ConfusionS;
        MemoC.Lines.AddStrings(tmpSL);
        FreeAndNil(tmpSL);
        ShowGeneralStats(MemoC,clstbl);
        PClsD:=clstbl.Items[0];
        LabelMol(LabelCell,PClsD,clstbl);
        //LblMod.Caption:='Model: '+IntToStr(clstbl.PredID);
        CLBMdls.ItemIndex:=clstbl.PredID;
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
        Mol2DViewC.ShowMOL(PClsD^.Id);
        Mol2DViewC.Refresh;
     end;
end;

//______________________________________________________________________________
//
//  FormCreate
//______________________________________________________________________________
procedure TConfMaFrm.FormCreate(Sender: TObject);
begin
     clstbl:=TClsTbl.Create;
     SDFFileReady := FALSE;
     SDFFile      := TStringList.Create;
     Mol2DViewC:=TMol2DView.Create(Self);
     with Mol2DViewC do begin
          Parent:=Self;
          Top:=PanelMOL.Top;
          Left:=PanelMOL.Left;
          Height:=PanelMOL.Height;
          Width:=PanelMOL.Width;
          DoubleBoundSpace := 3;
          StereoBoundWidth := 2;
     end;
end;  // FormCreate

//______________________________________________________________________________
//
//  BtnStartClick
//______________________________________________________________________________
procedure TConfMaFrm.BtnLaunchClick(Sender: TObject);
var
   tmpName: string;
   tmpSL: TStringList;
   PClsD: PTClsData;
begin
     SDFFileReady := FALSE;
     ClearGrid;  ///
     CLBMdls.Items.Clear;
     LabelCell.Caption := '';
     MemoC.Lines.Add('_______________________________________________');
     MemoC.Lines.Add('File: '+OpenDialogSDF.FileName);
     if ((ExtractFileExt(OpenDialogSDF.FileName)='.txt') or (ExtractFileExt(OpenDialogSDF.FileName)='.TXT')) then
        clstbl.ReadTXT(OpenDialogSDF.FileName);
     if ((ExtractFileExt(OpenDialogSDF.FileName)='.out') or (ExtractFileExt(OpenDialogSDF.FileName)='.OUT')) then
        clstbl.ReadOUT(OpenDialogSDF.FileName);
     if (EdtSDF1.Text='Select an SDF file...') then begin
        if (clstbl.SDFflenme<>'') then EdtSDF1.Text:=clstbl.SDFflenme;
     end else clstbl.SDFflenme:=EdtSDF1.Text;
     //
     CLBMdls.Visible:=True;
     if (clstbl.NPred>1) then begin
        BtNextMod.Enabled:=True; BtNextMod.Visible:=True;
        BtPrevMod.Enabled:=True; BtPrevMod.Visible:=True;
        BtVote.Enabled:=True; BtVote.Visible:=True;
        CLBMdls.Enabled:=True;
     end;
     //
     LoadGrid(StringGridFragCmp, clstbl);
     tmpSL:=clstbl.ClsStat.ConfusionS;
     MemoC.Lines.AddStrings(tmpSL);
     FreeAndNil(tmpSL);
     ShowGeneralStats(MemoC,clstbl);
     //
     StringGridFragCmp.Enabled:=TRUE;
     PClsD:=clstbl.Items[0];
     LabelMol(LabelCell,PClsD,clstbl);
     FreeAndNil(tmpSL);
     MaskEditGoto.Text:=IntToStr(PClsD^.Id);
     //LblMod.Caption:='Model: '+IntToStr(clstbl.PredID);
     CLBMdls.ItemIndex:=clstbl.PredID;
     LoadChkLstBox(CLBMdls,clstbl);
     tmpName:=ExpandFileName(clstbl.SDFflenme);
     if FileExists(tmpName) then begin
        Mol2DViewC.LoadSDFile(tmpName);
        Mol2DViewC.ShowMOL(PClsD^.Id);
        SDFFileReady := TRUE;
        BitBtnFirst.Enabled:=TRUE;
        BitBtnLeft.Enabled:=TRUE;
        BitBtnRight.Enabled:=TRUE;
        BitBtnLast.Enabled:=TRUE;
        BitBtnGoTo.Enabled:=TRUE;
        MaskEditGoto.Enabled:=TRUE;
        BitBtnFirst.Visible:=TRUE;
        BitBtnLeft.Visible:=TRUE;
        BitBtnRight.Visible:=TRUE;
        BitBtnLast.Visible:=TRUE;
        BitBtnGoTo.Visible:=TRUE;
        MaskEditGoto.Visible:=TRUE;
        PanelMatrix.Visible:=TRUE;
        LabelCell.Visible:=TRUE;
     end;
     Mol2DViewC.Refresh;
     //
     BtnLaunch.Enabled:=False;
     BtnLaunch.Visible:=False;
end;  // MenuOpenClick

procedure TConfMaFrm.BtPrevModClick(Sender: TObject);
var
   PClsD: PTClsData;
   tmpSL: TStringList;
begin
     if (clstbl.PrevPred) then begin
        MemoC.Clear;
        Welcome(MemoC);
        ClearGrid;
        LoadGrid(StringGridFragCmp, clstbl);
        tmpSL:=clstbl.ClsStat.ConfusionS;
        MemoC.Lines.AddStrings(tmpSL);
        FreeAndNil(tmpSL);
        ShowGeneralStats(MemoC,clstbl);
        PClsD:=clstbl.Items[0];
        LabelMol(LabelCell,PClsD,clstbl);
        //LblMod.Caption:='Model: '+IntToStr(clstbl.PredID);
        CLBMdls.ItemIndex:=clstbl.PredID;
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
        Mol2DViewC.ShowMOL(PClsD^.Id);
        Mol2DViewC.Refresh;
     end;
end;

procedure TConfMaFrm.BtNextModClick(Sender: TObject);
var
   PClsD: PTClsData;
   tmpSL: TStringList;
begin
     if (clstbl.NextPred) then begin
        MemoC.Clear;
        Welcome(MemoC);
        ClearGrid;
        LoadGrid(StringGridFragCmp,clstbl);
        tmpSL:=clstbl.ClsStat.ConfusionS;
        MemoC.Lines.AddStrings(tmpSL);
        FreeAndNil(tmpSL);
        ShowGeneralStats(MemoC,clstbl);
        PClsD:=clstbl.Items[0];
        LabelMol(LabelCell,PClsD,clstbl);
        //LblMod.Caption:='Model: '+IntToStr(clstbl.PredID);
        CLBMdls.ItemIndex:=clstbl.PredID;
        MaskEditGoto.Text:=IntToStr(PClsD^.Id);
        Mol2DViewC.ShowMOL(PClsD^.Id);
        Mol2DViewC.Refresh;
     end;
end;

procedure TConfMaFrm.BtMClearClick(Sender: TObject);
begin
     MemoC.Clear;
end;

procedure TConfMaFrm.BtQuitClick(Sender: TObject);
begin
     Close;
end;

procedure TConfMaFrm.BtSDFSelClick(Sender: TObject);
var
   FileExt: string[4];
begin
     if OpenDialogSDF.Execute then
        EdtSDF.Text:=OpenDialogSDF.FileName;
     FileExt := AnsiUpperCase(ExtractFileExt(OpenDialogSDF.FileName));
     if FileExists(OpenDialogSDF.FileName) and ((FileExt = '.TXT') or (FileExt='.OUT')) then begin
        BtnLaunch.Enabled := TRUE;
        BtnLaunch.Visible:=TRUE;
     end else
         ShowMessage('ERROR: File '+OpenDialogSDF.FileName+
                             ' does not exist or is not of type TXT.');
end;

procedure TConfMaFrm.FormDestroy(Sender: TObject);
begin
     FreeAndNil(SDFFile);
     FreeAndNil(clstbl);
     FreeAndNil(Mol2DViewC);
end;

procedure TConfMaFrm.BtSDFSel1Click(Sender: TObject);
begin
     if OpenDialogSDF1.Execute then
        edtSDF1.Text:=OpenDialogSDF1.FileName;
     if not FileExists(OpenDialogSDF1.FileName) then
        ShowMessage('Warning: File '+OpenDialogSDF1.FileName+' does not exist.');
end;

procedure TConfMaFrm.BtVoteClick(Sender: TObject);
var
   i: integer;
begin
     for i:=0 to CLBMdls.Items.Count-1 do
         if (CLBMdls.Checked[i]) then clstbl.SetWeightVal(i,1)
         else clstbl.SetWeightVal(i,0);
     MajorityVote(MemoC,clstbl);
end;

procedure TConfMaFrm.CLBMdlsClick(Sender: TObject);
begin
     PredUpdate;
end;

procedure TConfMaFrm.CLBMdlsItemClick(Sender: TObject; Index: integer);
begin
     PredUpdate;
end;

procedure TConfMaFrm.CLBMdlsKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     PredUpdate;
end;

procedure TConfMaFrm.CLBMdlsKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     PredUpdate;
end;

initialization
  {$I unitconfmafrm.lrs}

end.

