unit ufrmWizard;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, ComCtrls, jpeg, cxGraphics, cxLookAndFeels,
  cxLookAndFeelPainters, Menus, StdCtrls, cxButtons, UDefs, Util,
  JvExControls, JvSpecialProgress;

type
  TEvento = procedure ( sender: TObject) of object;

  TPageState = (psDiscard, psUse, psShowing, psHidded);
  TPageStateSet = set of TPageState;
  TPageReturn = (prRetornable, prNonRetornable, prFinal, prInicial, prMeio, prCancelable);
  TPageReturnSet = set of TPageReturn;
  TPageAction = (aAvancar, aRetroceder, aCancelar, aFinalizar);

  TBotao = (btCancelar, btVoltar, btAvancar, btFinalizar);
  TBotoes = set of TBotao;

  TPagina = class
  private
    FParent: TPageControl;
    FPagina: TTabSheet;
    FForm: TWinControl; // é o form que vai aderir à esta Página (tabsheet)
    FControles: TPanel;
    FInfo: TLabel;

    FNivel: Integer;
    FAlias: string;
    FDescription: string;

    FState: TPageStateSet;
    FPageReturn: TPageReturnSet;
    FBotoes: TBotoes;
    //FBotao: TBotao;

  protected
    procedure incState(aState: TPageState);
    procedure decState(aState: TPageState);
    procedure incPageReturn(aState: TPageReturn);
    procedure decPageReturn(aState: TPageReturn);

    procedure Mostrar(aMostrar: Boolean = true);

    procedure ConfigButtons(aButtons: TBotoes);
    procedure incButton(aBotao: TBotao);
    procedure decButton(aBotao: TBotao);
  public
    constructor Create;
    destructor destroy;

    procedure Add(aNivel: Integer; aAlias, aDescription: string; aForm: TWinControl; aPages: TPageControl; aControles: TPanel; aLabel: TLabel; aRetornavel: TPageReturnSet = [prRetornable]);
    procedure Descartar;
    procedure Usar;
    procedure SetRetornable(aRetornable: TPageReturnSet);

    property iNivel: integer read FNivel write FNivel;
    property iAlias: string read FAlias write FAlias;
    property iDescription: string read FDescription write FDescription;
  end;
  TPaginas = array of TPagina;

  TPaginasX = class
  private
    FPaginas: TPaginas;

    FNivel: Integer;
    FIndex: integer;
    FCount: Integer;
    FAlias: string;

  protected
  public
    constructor create;
    destructor destroy;

    procedure Add(aNivel: Integer; aAlias, aDescription: string; aForm: TWinControl; aPages: TPageControl; aControles: TPanel; aLabel: TLabel; aRetornavel: TPageReturnSet = [prRetornable]);
    {1 encontrou e mostrou 0 nao encontrou precisa adicionar... }
    function Mostrar(aNivel: Integer; aAlias: string; aAcao: TPageAction): integer;
    procedure MostrarNivel(aNivel: Integer);
    procedure SetButtons(aBotoes: TBotoes);
    procedure SetRetornable(aRetornable: TPageReturnSet);
    function GetAliasNivel(aNivel: Integer): string;

    property iNivel: Integer read FNivel write FNivel;
    property iIndex: integer read FIndex write FIndex;
    property iAlias: string read FAlias write FAlias;
  end;

  TfrmWizard = class(TForm)
    imgLogo: TImage;
    pgcWizard: TPageControl;
    pnlWizard: TPanel;
    btnCancelar: TcxButton;
    btnRetroceder: TcxButton;
    btnAvancar: TcxButton;
    btnFinaizar: TcxButton;
    lblInfo: TLabel;
    lblSite: TLabel;
    pbarWizard: TJvSpecialProgress;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FPaginas: TPaginasX;
    FInfo: string;
    FCancelar: TEvento;
    FVoltar: TEvento;
    FAvancar: TEvento;
    FFinalizar: TEvento;
    FPBarVisible: boolean;
    FPBarMin: Integer;
    FPBarPos: Integer;
    FPBarMax: Integer;
    procedure SetInfo(const Value: string);
    procedure SetAvancar(const Value: TEvento);
    procedure SetCancelar(const Value: TEvento);
    procedure SetFinalizar(const Value: TEvento);
    procedure SetVoltar(const Value: TEvento);
    procedure SetPBarMax(const Value: Integer);
    procedure SetPBarMin(const Value: Integer);
    procedure SetPBarPos(const Value: Integer);
    procedure SetPBarVisible(const Value: boolean);

  public
    { Public declarations }

    procedure iMostrar(aNivel:Integer; aAlias, aDescription: string; aAcao: TPageAction; aWinControl: TWinControl = nil; aRetornavel: TPageReturnSet = [prRetornable]);//1,'PessoaFisica',aAvancar
    procedure iMostrarNivel(aNivel: Integer);

    property iPaginas: TPaginasX read FPaginas write FPaginas;
    property iInfo: string read FInfo write SetInfo;
    property iCancelar: TEvento read FCancelar write SetCancelar;
    property iVoltar: TEvento read FVoltar write SetVoltar;
    property iAvancar: TEvento read FAvancar write SetAvancar;
    property iFinalizar: TEvento read FFinalizar write SetFinalizar;
    property iPBarMin: Integer read FPBarMin write SetPBarMin;
    property iPBarMax: Integer read FPBarMax write SetPBarMax;
    property iPBarPos: Integer read FPBarPos write SetPBarPos;
    property iPBarVisible: boolean read FPBarVisible write SetPBarVisible;
  end;

var
  frmWizard: TfrmWizard;

implementation

uses uPessoaFisica;

{$R *.dfm}

{ TPagina }

procedure TPagina.Add(aNivel: Integer; aAlias, aDescription: string;
  aForm: TWinControl; aPages: TPageControl; aControles: TPanel; aLabel: TLabel; aRetornavel: TPageReturnSet = [prRetornable]);
begin
  FControles:= aControles;
  FParent:= aPages;
  FForm:= aForm;
  FInfo:= aLabel;
  FDescription:= aDescription;
  FNivel:= aNivel;
  FAlias:= aAlias;
  FPageReturn:= aRetornavel;
  
  FPagina:= TTabSheet.Create(FParent);
  //FPagina.Parent := FParent;
  with FPagina do
  begin
    Caption:= aAlias;
    PageControl:= FParent;
    TabVisible:= false;
  end;
  with FForm do
  begin
    ManualDock(FPagina);
    Align:= alClient;
    Show;
  end;
end;

procedure TPagina.ConfigButtons(aButtons: TBotoes);
var
  i: Integer;
begin
  FBotoes:= aButtons;
  for i:= 0 to FControles.ComponentCount-1 do
  if FControles.Components[i] is TcxButton then
  begin
    if (TcxButton(FControles.Components[i]).Caption = 'Cancelar')
      and (btCancelar in FBotoes) then TcxButton(FControles.Components[i]).Visible:= True
    else TcxButton(FControles.Components[i]).Visible:= False;
    if (TcxButton(FControles.Components[i]).Caption = 'Voltar')
      and (btVoltar in FBotoes) then TcxButton(FControles.Components[i]).Visible:= True
    else TcxButton(FControles.Components[i]).Visible:= False;
    if (TcxButton(FControles.Components[i]).Caption = 'Avançar')
      and (btAvancar in FBotoes) then TcxButton(FControles.Components[i]).Visible:= True
    else TcxButton(FControles.Components[i]).Visible:= False;
    if (TcxButton(FControles.Components[i]).Caption = 'Finalizar')
      and (btFinalizar in FBotoes) then TcxButton(FControles.Components[i]).Visible:= True
    else TcxButton(FControles.Components[i]).Visible:= False;
  end;
end;

constructor TPagina.Create;
begin
  inherited;
  FParent:= nil;
  FPagina:= nil;
  FForm:= nil;
  FControles:= nil;
  FInfo:= nil;
  FNivel:=0;
  FAlias:='';
  FDescription:='';
  FState:= [psHidded];
  FPageReturn:= [prRetornable];
  //ConfigButtons([btCancelar,btAvancar]);
end;

procedure TPagina.decButton(aBotao: TBotao);
var
  i: integer;
begin
  for i:= 0 to FControles.ControlCount -1 do
  begin
  if FControles.Controls[i].ClassName = 'TcxButton' then
  begin
    if (TcxButton(FControles.Controls[i]).Caption = 'Cancelar')
      and (btCancelar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= false;
    if (TcxButton(FControles.Controls[i]).Caption = 'Voltar')
      and (btVoltar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= false;
    if (TcxButton(FControles.Controls[i]).Caption = 'Avançar')
      and (btAvancar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= false;
    if (TcxButton(FControles.Controls[i]).Caption = 'Finalizar')
      and (btFinalizar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= false;
  end;
  end;
  if aBotao in FBotoes then
    Exclude(FBotoes,aBotao);
end;

procedure TPagina.decPageReturn(aState: TPageReturn);
begin
  if aState in FPageReturn then
    Exclude(FPageReturn,aState);
end;

procedure TPagina.decState(aState: TPageState);
begin
  if aState in FState then
    Exclude(FState,aState);
end;

procedure TPagina.Descartar;
begin
  Mostrar(false);
  incState(psDiscard);
  decState(psUse);
end;

destructor TPagina.destroy;
begin
//  FForm.Free;
  FPagina.Free;
  FParent.Free;
end;

procedure TPagina.incButton(aBotao: TBotao);
var
  i: integer;
begin
  if not(aBotao in FBotoes) then
    Include(FBotoes,aBotao);
  for i:= 0 to FControles.ControlCount-1 do
  if FControles.Controls[i] is TcxButton then
  begin
    if (TcxButton(FControles.Controls[i]).Caption = 'Cancelar')
      and (btCancelar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= True;
    if (TcxButton(FControles.Controls[i]).Caption = 'Voltar')
      and (btVoltar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= True;
    if (TcxButton(FControles.Controls[i]).Caption = 'Avançar')
      and (btAvancar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= True;
    if (TcxButton(FControles.Controls[i]).Caption = 'Finalizar')
      and (btFinalizar = aBotao) then TcxButton(FControles.Controls[i]).Visible:= True;
  end;
end;

procedure TPagina.incPageReturn(aState: TPageReturn);
begin
  if not(aState in FPageReturn) then
    Include(FPageReturn,aState);
end;

procedure TPagina.incState(aState: TPageState);
begin
  if not(aState in FState) then
    Include(FState,aState);
end;

procedure TPagina.Mostrar(aMostrar: Boolean);
begin
  FPagina.Visible:= aMostrar;
  if aMostrar then
  begin
    UpTabs(FParent,FAlias);
    FForm.Show;
    incState(psShowing);
    decState(psHidded);
  end else
  begin
    incState(psHidded);
    decState(psShowing);
  end;
end;

procedure TPagina.SetRetornable(aRetornable: TPageReturnSet);
var
  i: Integer;
  vPageReturn: TPageReturnSet;
begin
  vPageReturn:= aRetornable;
  FPageReturn:= vPageReturn;
  //remoção automática
  if prNonRetornable in vPageReturn then decButton(btVoltar);
  if prRetornable in vPageReturn then incButton(btVoltar);
  if prCancelable in vPageReturn then incButton(btCancelar) else decButton(btCancelar);

  //testes de configuração
  if prFinal in vPageReturn then
  begin
    incButton(btFinalizar);
    decButton(btAvancar);
  end;
  if prMeio in vPageReturn then
  begin
//    if prFinal in vPageReturn then begin decButton(btFinalizar); decPageReturn(prFinal);end;
//    if prInicial in vPageReturn then decPageReturn(prInicial);
//    if prRetornable in vPageReturn then incButton(btVoltar)
//    else decButton(btVoltar);
  end;
  if prInicial in vPageReturn then
  begin
    decButton(btVoltar);
    decButton(btFinalizar);
    incButton(btAvancar);
//    if prMeio in vPageReturn then decPageReturn(prMeio);
  end;
  
end;

procedure TPagina.Usar;
begin
  Mostrar();
  incState(psUse);
  decState(psDiscard);
  SetRetornable(FPageReturn);
//  if prNonRetornable in FPageReturn then decButton(btVoltar);
//  if prFinal in FPageReturn then incButton(btFinalizar);
//  if prMeio in FPageReturn then
//  begin
//    decButton(btFinalizar);
//    if prRetornable in FPageReturn then incButton(btVoltar) else decButton(btVoltar);
//  end;
//  if prInicial in FPageReturn then begin decButton(btVoltar); decButton(btFinalizar); end;
  FInfo.Caption:= FDescription;
end;

{ TPaginasX }

procedure TPaginasX.Add(aNivel: Integer; aAlias, aDescription: string;
  aForm: TWinControl; aPages: TPageControl; aControles: TPanel; aLabel: TLabel; aRetornavel: TPageReturnSet = [prRetornable]);
begin
  Inc(FCount);
  FIndex:= FCount -1;
  FNivel:= aNivel;
  FAlias:= aAlias;
  SetLength(FPaginas,FCount);
  FPaginas[FIndex]:= TPagina.Create;
  FPaginas[FIndex].Add(aNivel,aAlias,aDescription,aForm,aPages,aControles, aLabel);
  //Os novos valores só funcionam a partir daqui.
  FPaginas[FIndex].SetRetornable(aRetornavel);
  FPaginas[FIndex].Usar;
end;

constructor TPaginasX.create;
begin
  FPaginas:= nil;
  FCount:= 0;
  FIndex:=0;
  FNivel:=0;
  FAlias:='';
end;

destructor TPaginasX.destroy;
var
  i: Integer;
begin
  for i:= 0 to FCount do
  FPaginas[i].Free;
end;

function TPaginasX.GetAliasNivel(aNivel: Integer): string;
var
  i: Integer;
begin
  {}
  for i:= 0 to High(FPaginas) do
  begin
    if FPaginas[i].FNivel = aNivel then
      if psUse in FPaginas[i].FState then
      begin
        result:= FPaginas[i].FAlias;
        Break;
      end;
  end;
end;

function TPaginasX.Mostrar(aNivel: Integer; aAlias: string;
  aAcao: TPageAction): integer;
var
  i: Integer;
begin
  result:=0;

  if aAcao = aAvancar then
  begin
    FPaginas[FIndex].incState(psUse);
    FPaginas[FIndex].decState(psDiscard);
  end else if aAcao = aRetroceder then
  begin
    FPaginas[FIndex].incState(psDiscard);
    FPaginas[FIndex].decState(psUse);
  end;

  if FCount <> 0 then
    for i:=0 to FCount do
    if FPaginas[i].FAlias = aAlias then
    begin
      FPaginas[i].Usar;
      FNivel:= aNivel;
      FIndex:= i;
      FAlias:= aAlias;
      Result:=1;
      Break;
    end;
end;

procedure TPaginasX.MostrarNivel(aNivel: Integer);
var
  i: Integer;
begin
  {}
  for i:= 0 to High(FPaginas) do
  begin
    if FPaginas[i].FNivel = aNivel then
      if psUse in FPaginas[i].FState then
      begin
        FPaginas[i].Usar;
        FNivel:= aNivel;
        FIndex:= i;
        FAlias:= FPaginas[i].FAlias;
        Break;
      end;
  end;
end;

procedure TPaginasX.SetButtons(aBotoes: TBotoes);
begin
//  FPaginas[FIndex].SetRetornable(aRetornable);
end;

procedure TPaginasX.SetRetornable(aRetornable: TPageReturnSet);
begin
  FPaginas[FIndex].SetRetornable(aRetornable);
end;

procedure TfrmWizard.FormClose(Sender: TObject; var Action: TCloseAction);
begin
//  FPaginas.Free;
end;

procedure TfrmWizard.FormCreate(Sender: TObject);
begin
  FPaginas:= TPaginasX.create;
end;

{ TfrmWizard }

procedure TfrmWizard.iMostrar(aNivel: Integer; aAlias, aDescription: string; 
  aAcao: TPageAction; aWinControl: TWinControl = nil; aRetornavel: TPageReturnSet = [prRetornable]);
begin
  try
    if iPaginas.Mostrar(aNivel,aAlias,aAcao) = 0
    then if aWinControl <> nil then iPaginas.Add(aNivel,aAlias,aDescription,aWinControl,self.pgcWizard,self.pnlWizard,self.lblInfo, aRetornavel);
  except
    iPaginas.Add(aNivel,aAlias,aDescription,aWinControl,self.pgcWizard,self.pnlWizard,self.lblInfo, aRetornavel);
    iPaginas.SetRetornable(aRetornavel);
  end;
end;

procedure TfrmWizard.iMostrarNivel(aNivel: Integer);
begin
  FPaginas.MostrarNivel(aNivel);
end;

procedure TfrmWizard.SetAvancar(const Value: TEvento);
begin
  FAvancar := Value;
  btnAvancar.OnClick:= Value;
end;

procedure TfrmWizard.SetCancelar(const Value: TEvento);
begin
  FCancelar := Value;
  btnCancelar.OnClick:= Value;
end;

procedure TfrmWizard.SetFinalizar(const Value: TEvento);
begin
  FFinalizar := Value;
  btnFinaizar.OnClick:= Value;
end;

procedure TfrmWizard.SetInfo(const Value: string);
begin
  FInfo := Value;
  lblInfo.Caption:= Value;
end;

procedure TfrmWizard.SetPBarMax(const Value: Integer);
begin
  FPBarMax := Value;
  Self.pbarWizard.Maximum:= Value;
end;

procedure TfrmWizard.SetPBarMin(const Value: Integer);
begin
  FPBarMin := Value;
  Self.pbarWizard.Minimum:= Value;
end;

procedure TfrmWizard.SetPBarPos(const Value: Integer);
begin
  FPBarPos := Value;
  Self.pbarWizard.Position:= Value;
end;

procedure TfrmWizard.SetPBarVisible(const Value: boolean);
begin
  FPBarVisible := Value;
  Self.pbarWizard.Visible:= Value;
end;

procedure TfrmWizard.SetVoltar(const Value: TEvento);
begin
  FVoltar := Value;
  btnRetroceder.OnClick:= Value;
end;

end.
