/// unit zobrazujuci Rule Table okno a Token Table okno
unit tableframe;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Grids, ComCtrls, ExtCtrls, hashmap, tables;

type
  /// trieda zobrazujuca tabulku
  TTableForm = class(TForm)
    Panel1: TPanel;
    StatusBar1: TStatusBar;
    StringGrid1: TStringGrid;
    procedure StringGrid1DblClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
  private
    { Private declarations }
  public
    isRuleTable: Boolean;
    constructor createNamed(owner: TComponent; name: TCaption);
    procedure fillAsTokenTable(T: TStrIntHashMap; N: TStrIntHashMap);
    procedure fillAsRuleTable(T: TStrIntHashMap; N: TStrIntHashMap; R: TRuleTable);
    { Public declarations }
  end;

var
  TokenTableForm: TTableForm;
  RuleTableForm: TTableForm;

implementation

{$R *.dfm}

uses constants, langres, folderdiff, mainframe, grammaredit;

(*
procedure LockControl(c: TWinControl; bLock: Boolean);
begin
  if (c = nil) or (c.Handle = 0) then
    Exit;
  if bLock then
    SendMessage(c.Handle, WM_SETREDRAW, 0, 0)
  else begin
    SendMessage(c.Handle, WM_SETREDRAW, 1, 0);
    RedrawWindow(c.Handle, nil, 0, RDW_ERASE or RDW_FRAME or RDW_INVALIDATE or RDW_ALLCHILDREN);
  end;
end;
*)

/// procedura volana pri zmene rozmerov okna, zmeni sirku stlpcov v tabulke
procedure TTableForm.FormResize(Sender: TObject);
var i: Integer;
begin
  for i := 0 to Pred(StringGrid1.ColCount) do
    StringGrid1.ColWidths[i] := StringGrid1.ClientWidth div StringGrid1.ColCount;
end;

/// procedura volana tesne po vytvoreni okna, ho inicializuje
procedure TTableForm.FormCreate(Sender: TObject);
begin
//  DoubleBuffered := true;
//  Panel1.DoubleBuffered := true;
  StringGrid1.Enabled := false;
  StringGrid1.DoubleBuffered := true;
end;

/// procedura naplni tabulku hodnotami z tabulky pravidiel(R),
/// pri tom vyuziva tabulky nazvov terminalov a neterminalov (T a N)
procedure TTableForm.fillAsRuleTable(T, N: TStrIntHashMap; R: TRuleTable);
var index,i: Integer;
    S,Sstate: xString;
    value,posit: Integer;
    regexp: xString;
    b: Boolean;
begin
  isRuleTable := false;
  with StringGrid1 do begin
    cells[0,0] := GetLangString(STR_RULENUMBER);
    cells[1,0] := GetLangString(STR_LEFT_SIDE);
    cells[2,0] := GetLangString(STR_POSITION);
    cells[3,0] := GetLangString(STR_RIGHT_SIDE);
    Tag := -1;
  end;

  StringGrid1.RowCount := 1 + R.count;
  with StringGrid1 do begin
    for index := 1 to R.count do begin
      cells[0,index] := IntToStr(index-1);
      value := R.rules[index-1].symbols[0];
      N.getByValue(value,S,posit,regexp);
      cells[1,index] := '<' + S + '>';
      cells[2,index] := IntToStr(R.rules[index-1].pos);
      Sstate := '';
      for i := 1 to Pred(R.rules[index-1].length) do begin
        value := R.rules[index-1].symbols[i];
        if value <= MAX_TERMINAL then begin
          b := T.getByValue(value,S,posit,regexp);
          if b then
            Sstate := Sstate + S + ' ';
        end
        else begin
          b := N.getByValue(value,S,posit,regexp);
          if b then
            Sstate := Sstate + '<' + S + '> '
        end;
        //!TODO! if not b => fatal, lebo ako inak by mohlo k tomu dojst
      end;
      cells[3,index] := Sstate;
    end;
  end;

  StatusBar1.Panels[0].Text := 'Number Of Rules: ' + IntToStr(R.count);
  StringGrid1.Enabled := true;
end;

/// procedura naplni tabulku hodnotami z tabuliek nazvov terminalov a neterminalov (T a N)
procedure TTableForm.fillAsTokenTable(T, N: TStrIntHashMap);
var h: Integer;
    lastentry: Integer;
    i: Integer;
    p: PStrIntEntry;
    S: xString;
    index: Integer;
    total: Integer;
begin
  isRuleTable := true;
  with StringGrid1 do begin
    cells[0,0] := GetLangString(STR_ID);
    cells[1,0] := GetLangString(STR_NAME);
    cells[2,0] := GetLangString(STR_POSITION);
    cells[3,0] := GetLangString(STR_REGEXP);
    Tag := -1;
  end;
  total := 0;
  StringGrid1.RowCount := 1 + T.FHashSet.getSize + N.FHashSet.getSize;

  S := '';
  index := 1;
  T.FHashSet.getNextReset;
  while T.FHashSet.getNext(i,Integer(p)) do begin
    with StringGrid1 do begin
      cells[0,index] := IntToStr(p.value);
      cells[1,index] := p.key;
      cells[2,index] := IntToStr(p.pos);
      cells[3,index] := p.regexp;
    end;
    index := index + 1;
  end;
//  total := total + index - 1;

  S := '';
//  index := 1;
  N.FHashSet.getNextReset;
  while N.FHashSet.getNext(i,Integer(p)) do begin
    with StringGrid1 do begin
      cells[0,index] := IntToStr(p.value);
      cells[1,index] := '<' + p.key + '>';
      cells[2,index] := IntToStr(p.pos);
      cells[3,index] := p.regexp;
    end;
    index := index + 1;
  end;
  total := index - 1;

  StatusBar1.Panels[0].Text := 'Number Of Terminals: ' + IntToStr(T.FHashSet.getSize) + ' , Number Of Non-terminals: ' + IntToStr(N.FHashSet.getSize) + ' => Total: ' + IntToStr(total);
  StringGrid1.Enabled := true;
end;

/// procedura obsluhujuca dvojklik mysou do tabulky, posunieme sa na adekvatne miesto v subore definujucom
/// gramatiku, resp. sa zobrazi ina tabulka popisujuca hodnotu na ktoru sme klikli
procedure TTableForm.StringGrid1DblClick(Sender: TObject);
var SG,SG2: TStringGrid;
    s: xString;
    s2: xString;
    sname,s2name: xString;
    mpos: TPoint;
    X,Y: Integer;
    ACol,ARow: Integer;
begin
//  if not (Sender is TStringGrid) then
//    Exit;
//  SG := TStringGrid(Sender);
  SG := StringGrid1;

  mpos := Mouse.CursorPos;
  X := SG.ScreenToClient(mpos).X;
  Y := SG.ScreenToClient(mpos).Y;
  SG.MouseToCell(X, Y, ACol, ARow);

  if ARow = 0 then begin
    if (ACol = 0) or (ACol = 2) then begin
      GridSort(SG,ACol,1,SG.RowCount-1,celltypeInteger);
    end
    else begin
      GridSort(SG,ACol,1,SG.RowCount-1,celltypeString);
    end;
    Exit;
  end
  else if (ARow > 0) and (ARow < SG.RowCount) then begin
    MainForm.ShowGrammarEditTBClick(Sender);
    GrammarEditForm.CaretGotoPos(StrToIntDef(SG.Cells[2,ARow],-1));
  end;
end;

/// konstruktor vytvarajuci objekt typu TTableForm s captionom name, vlastneny ownerom
constructor TTableForm.createNamed(owner: TComponent; name: TCaption);
begin
  inherited create(owner);
  caption := name;
end;

end.
