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, dxSkinsCore, dxSkinBlack, dxSkinBlue,
  dxSkinBlueprint, dxSkinCaramel, dxSkinCoffee, dxSkinDarkRoom, dxSkinDarkSide,
  dxSkinDevExpressDarkStyle, dxSkinDevExpressStyle, dxSkinFoggy,
  dxSkinGlassOceans, dxSkinHighContrast, dxSkiniMaginary, dxSkinLilian,
  dxSkinLiquidSky, dxSkinLondonLiquidSky, dxSkinMcSkin, dxSkinMoneyTwins,
  dxSkinOffice2007Black, dxSkinOffice2007Blue, dxSkinOffice2007Green,
  dxSkinOffice2007Pink, dxSkinOffice2007Silver, dxSkinOffice2010Black,
  dxSkinOffice2010Blue, dxSkinOffice2010Silver, dxSkinPumpkin, dxSkinSeven,
  dxSkinSevenClassic, dxSkinSharp, dxSkinSharpPlus, dxSkinSilver,
  dxSkinSpringTime, dxSkinStardust, dxSkinSummer2008, dxSkinTheAsphaltWorld,
  dxSkinsDefaultPainters, dxSkinValentine, dxSkinVS2010, dxSkinWhiteprint,
  dxSkinXmas2008Blue, dxGDIPlusClasses, JvExExtCtrls, JvImage;

type

  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)
    pgcWizard: TPageControl;
    pnlWizard: TPanel;
    btnCancelar: TcxButton;
    btnRetroceder: TcxButton;
    btnAvancar: TcxButton;
    btnFinaizar: TcxButton;
    lblInfo: TLabel;
    lblSite: TLabel;
    pbarWizard: TJvSpecialProgress;
    jvImg1: TJvImage;
    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(btAvancar);
//    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;
  Action:= caHide;
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.
