{-----------------------------------------------------------------------------
The contents of this file are subject to the Mozilla Public License
Version 1.1 (the "License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/MPL-1.1.html

Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
the specific language governing rights and limitations under the License.

The Original Code is: Main.pas, released on 2004-03-29.

The Initial Developer of the Original Code is Andreas Hausladen
(Andreas dott Hausladen att gmx dott de)
Portions created by Andreas Hausladen are Copyright (C) 2004 Andreas Hausladen.
All Rights Reserved.

Contributor(s): -

You may retrieve the latest version of this file at the Project JEDI's JVCL
home page, located at http://jvcl.sourceforge.net

Known Issues:
-----------------------------------------------------------------------------}
// $Id: Main.pas 11014 2006-11-12 08:45:22Z ahuser $

{
  command line arguments:
    --help              Shows the help screen with all options
}

unit Main;

{$I jvcl.inc}
{$IFNDEF INSTALLER}
 {$IFDEF COMPILER6_UP}
  {$MESSAGE FATAL 'Wrong jvcl.inc was used. The jvcl3\install\JVCLInstall\jvcl.inc should have been used.'}
 {$ELSE}
   'Wrong jvcl.inc was used. The jvcl3\install\JVCLInstall\jvcl.inc should have been used.'
 {$ENDIF COMPILER6_UP}
{$ENDIF !INSTALLER}

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, ImgList,
  Dialogs, JvExControls, JvComponent, jpeg, ExtCtrls, StdCtrls, JvWizard,
  JvWizardRouteMapList,
  {$IFDEF USE_DXGETTEXT}
  JvGnugettext,
  {$ENDIF USE_DXGETTEXT}
  Core,
  ShellAPI, HtHint;

type
  TFormMain = class(TJvForm)
    JvWizard: TJvWizard;
    ImageList: TImageList;
    JvWizardRouteMapList: TJvWizardRouteMapList;
    LblHomepage: TLabel;
    ImageListCheckMark: TImageList;
    PanelLogo: TPanel;
    ImageLogo: TImage;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure JvWizardActivePageChanging(Sender: TObject;
      var ToPage: TJvWizardCustomPage);
    procedure JvWizardFinishButtonClick(Sender: TObject);
    procedure JvWizardCancelButtonClick(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
    procedure JvWizardActivePageChanged(Sender: TObject);
    procedure ImageLogoClick(Sender: TObject);
    procedure JvWizardRouteMapNodes1Displaying(Sender: TObject;
      const Page: TJvWizardCustomPage; var AllowDisplay: Boolean);
    procedure LblHomepageClick(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure JvWizardRouteMapListDrawItem(Sender: TObject;
      ACanvas: TCanvas; ARect: TRect; MousePos: TPoint; PageIndex: Integer;
      var DefaultDraw: Boolean);
  private
    FAppStartFailed: Boolean;
    FFinished: Boolean;
    function BuildPages(Inst: IInstallerPage): TWinControl;
  protected
    procedure DoPagesChanged(Sender: TObject);
    procedure DoPageRecreate(Sender: TObject);
    procedure DoUpdateNavigation(Sender: TObject);
    procedure DoPageShow(Sender: TObject);
    procedure DoTranslate(Sender: TObject);
    procedure DoFinished(Sender: TObject);

    procedure RecreatePage(var Msg: TMessage); message WM_USER + 1;
  public
    property AppStartFailed: Boolean read FAppStartFailed write FAppStartFailed;
    property Finished: Boolean read FFinished write FFinished;
  end;

var
  FormMain: TFormMain;

implementation

uses
  Math,
  InstallerConsts, PageBuilder, JvConsts, JvResources, Utils;

(* // Main.pas  - see InstallerConsts.pas
resourcestring
  RsBtnInstall = '&Install';
  RsBtnUninstall = '&Uninstall';
  RsNoPackageInstaller = 'Application error. No PackageInstaller created.';
  RsCancelInstallation = 'Do you really want to cancel the installation?';

  RsJediHomepage = 'http://projectjedi.sourceforge.net';
  RsJVCLHomepage = 'http://jvcl.sourceforge.net';
*)

{$R *.dfm}
{$R WinXP.res}

procedure TFormMain.DoPagesChanged(Sender: TObject);
begin
  BuildPages(PackageInstaller.Page.NextPage);
end;

procedure TFormMain.DoPageRecreate(Sender: TObject);
begin
  // Could be called by an event handler of a component that will be destroyed.
  PostMessage(Handle, WM_USER + 1, 0, Integer(Sender));
end;

procedure TFormMain.RecreatePage(var Msg: TMessage);
begin
  if JvWizard.ActivePage <> nil then
  begin
    DestroyPage(TJvWizardInteriorPage(JvWizard.ActivePage));
    PackageInstaller.Page.Init;
    PreparePage(TJvWizardInteriorPage(JvWizard.ActivePage), PackageInstaller.Page);
    DoPageShow(JvWizard.ActivePage);
    DoPagesChanged(TObject(Msg.LParam));
  end;
end;

procedure TFormMain.DoPageShow(Sender: TObject);
var
  Ctrl: TWinControl;
begin
  PackageInstaller.BeginUpdate;
  try
    Ctrl := CreatePage(Sender as TJvWizardInteriorPage, PackageInstaller.Page);
    while (Ctrl <> nil) and (not Ctrl.Enabled) do
      Ctrl := FindNextControl(Ctrl, True, False, False);
    ActiveControl := Ctrl;
    DoUpdateNavigation(Sender);
  finally
    PackageInstaller.EndUpdate;
  end;

  if Supports(PackageInstaller.Page.NextPage, IInstallPage) then
    JvWizard.ButtonNext.Caption := RsBtnInstall
  else if Supports(PackageInstaller.Page.NextPage, IUninstallPage) then
    JvWizard.ButtonNext.Caption := RsBtnUninstall
  else
    JvWizard.ButtonNext.Caption := RsNextButtonCaption;
end;

function TFormMain.BuildPages(Inst: IInstallerPage): TWinControl;
var
  Page: TJvWizardInteriorPage;
  Index: Integer;
begin
  PackageInstaller.BeginUpdate;
  try
    Result := nil;
   // remove old pages
    Index := JvWizard.ActivePageIndex;
    while Index + 1 < JvWizard.PageCount do
    begin
     // First remove ActionList from the frame (bug in VCL).
      DestroyPage(JvWizard.WizardPages[JvWizard.PageCount - 1] as TJvWizardInteriorPage);
      JvWizard.WizardPages[JvWizard.PageCount - 1].Free;
    end;

    Page := nil;
    while Inst <> nil do
    begin
      Page := TJvWizardInteriorPage.Create(JvWizard);
      Page.Wizard := JvWizard;
      Page.Header.Height := 50;
      PreparePage(Page, Inst);
      Page.OnPage := DoPageShow;

      Inst := Inst.NextPage; // create next page
    end;
    if Page <> nil then
    begin
      Page.VisibleButtons := Page.VisibleButtons + [bkFinish] - [bkNext];
      Page.EnableButton(bkCancel, False);
    end;
  finally
    PackageInstaller.EndUpdate;
  end;
end;

procedure TFormMain.DoUpdateNavigation(Sender: TObject);
begin
  if JvWizard.ActivePage <> nil then
  begin
    JvWizard.ActivePage.EnableButton(bkBack, PackageInstaller.CanPrevPage);
    JvWizard.ActivePage.EnableButton(bkNext, PackageInstaller.CanNextPage);
  end;
end;

procedure TFormMain.DoFinished(Sender: TObject);
begin
  Finished := True;
  JvWizardRouteMapList.Invalidate;
end;

procedure TFormMain.FormCreate(Sender: TObject);
begin
  Application.HintHidePause := MaxInt;
  Forms.HintWindowClass := THtHintWindow;
  Application.ShowHint := False;
  Application.ShowHint := True;

  if PackageInstaller = nil then
  begin
    MessageDlg(RsNoPackageInstaller, mtError, [mbOk], 0);
    AppStartFailed := True;
    Application.ShowMainForm := False;
    Application.Terminate;
  end;
  PackageInstaller.OnPagesChanged := DoPagesChanged;
  PackageInstaller.OnPageRecreate := DoPageRecreate;
  PackageInstaller.OnUpdateNavigation := DoUpdateNavigation;
  PackageInstaller.OnTranslate := DoTranslate;
  PackageInstaller.OnFinished := DoFinished;

  Caption := PackageInstaller.Installer.InstallerName;
  Application.Title := Caption;

  if not PackageInstaller.Installer.CanInstall then
  begin
    Application.ShowMainForm := False;
    Application.Terminate;
    Exit;
  end;

  // create welcome page
  BuildPages(PackageInstaller.Page);
  JvWizard.SelectFirstPage;
  
  // for some reason, the label doesn't get translated 
  // if we don't do it ourselves
  DoTranslate(LblHomepage);
end;

procedure TFormMain.FormDestroy(Sender: TObject);
begin
  if AppStartFailed then
    Exit; // do not free any memory that is not allocated
end;

procedure TFormMain.JvWizardActivePageChanging(Sender: TObject;
  var ToPage: TJvWizardCustomPage);
var
  Index: Integer;
begin
  Index := JvWizard.ActivePageIndex;
  if (ToPage = nil) or (Index = -1) then
    Exit;
  if Index < ToPage.PageIndex then
  begin
    while Index < ToPage.PageIndex do
    begin
      if not PackageInstaller.CanNextPage then
      begin
        ToPage := JvWizard.WizardPages[Index];
        Break;
      end;
      PackageInstaller.GoToNextPage;
      Inc(Index);
    end;
  end
  else
  begin
    while Index > ToPage.PageIndex do
    begin
      if not PackageInstaller.CanPrevPage then
      begin                 
        ToPage := JvWizard.WizardPages[Index];
        Break;
      end;
      PackageInstaller.GoToPrevPage;
      Dec(Index);
    end;
  end;
end;

procedure TFormMain.JvWizardFinishButtonClick(Sender: TObject);
begin
  Finished := True;
  PackageInstaller.Installer.Finish;
  Close;
end;

procedure TFormMain.JvWizardCancelButtonClick(Sender: TObject);
begin
  Close;
end;

procedure TFormMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var
  InstallPage: IInstallPage;
begin
  if not Finished then
  begin
    if Supports(PackageInstaller.Page, IInstallPage, InstallPage) and
       (JvWizard.ActivePage.EnabledButtons = []) then
      { The installation cannot be aborted without leaving make.exe and cmd.exe
        running for ever. So we do not allow abortion. }
      CanClose := False
    else
    CanClose := MessageDlg(RsCancelInstallation,
      mtConfirmation, [mbYes, mbNo], 0) = mrYes;
  end;
end;

procedure TFormMain.JvWizardActivePageChanged(Sender: TObject);

  procedure AdjustButton(Btn: TJvWizardNavigateButton);
  begin
    Btn.Width := Max(Btn.Width, Canvas.TextWidth(Btn.Caption) + 16);
  end;

var
  Buttons: TJvWizardButtonSet;
begin
  Finished := False; // as long as the user navigates the installation is not finished 

  PanelLogo.BringToFront;
  if PackageInstaller.Page <> nil then
  begin
    Buttons := JvWizard.ActivePage.EnabledButtons;
    JvWizard.ActivePage.EnabledButtons := [];
    try
      PackageInstaller.Page.Action;
    finally
      JvWizard.ActivePage.EnabledButtons := Buttons;
    end;
  end;

 // adjust buttons if necessary
  AdjustButton(JvWizard.ButtonStart);
  AdjustButton(JvWizard.ButtonLast);
  AdjustButton(JvWizard.ButtonBack);
  AdjustButton(JvWizard.ButtonNext);
  AdjustButton(JvWizard.ButtonFinish);
  AdjustButton(JvWizard.ButtonCancel);
  AdjustButton(JvWizard.ButtonHelp);
end;

procedure TFormMain.ImageLogoClick(Sender: TObject);
begin
  ShellExecute(Handle, 'open', PChar(RsJediHomepage), // do not localize
    nil, nil, SW_SHOWNORMAL);
end;

procedure TFormMain.JvWizardRouteMapNodes1Displaying(Sender: TObject;
  const Page: TJvWizardCustomPage; var AllowDisplay: Boolean);
begin
  AllowDisplay := Page.PageIndex < Page.Wizard.PageCount - 1;
end;

procedure TFormMain.LblHomepageClick(Sender: TObject);
begin
  ShellExecute(Handle, 'open', PChar(RsJVCLHomepage), // do not localize
    nil, nil, SW_SHOWNORMAL);
end;

procedure TFormMain.FormPaint(Sender: TObject);
var
  Page: IInstallerPage;
begin
  if Tag <> 0 then
    Exit;
  Tag := 1;

 // auto installation
  if PackageInstaller.Installer.AutoInstall then
  begin
    while True do
    begin
      Page := PackageInstaller.Page.NextPage;
      if (Page = nil) then
        Break;
      if Supports(Page, IInstallPage) or Supports(Page, IUninstallPage) then
      begin
        JvWizard.SelectNextPage;
        Break;
      end;
      Page := nil;
      JvWizard.SelectNextPage;
    end;
  end;
end;

procedure TFormMain.JvWizardRouteMapListDrawItem(Sender: TObject;
  ACanvas: TCanvas; ARect: TRect; MousePos: TPoint; PageIndex: Integer;
  var DefaultDraw: Boolean);
begin
  DefaultDraw := True;
  if (PageIndex < JvWizard.ActivePageIndex) or
     ((PageIndex = JvWizard.ActivePageIndex) and Finished) then
  begin
    ACanvas.Font.Color := clSilver;
    ImageListCheckMark.Draw(ACanvas,
      ARect.Left - 5,
      ARect.Top + (ACanvas.TextHeight('Ag') - ImageListCheckMark.Height) div 2 + 4,
      0);
  end;
end;

procedure TFormMain.DoTranslate(Sender: TObject);
begin
  {$IFDEF USE_DXGETTEXT}
  TranslateComponent(TComponent(Sender), 'JVCLInstall');
  {$ENDIF USE_DXGETTEXT}
end;

{$IFDEF USE_DXGETTEXT}

procedure InitDxgettext;
var
  Path: string;
begin
  Path := ExtractFilePath(ExtractFileDir(ParamStr(0))) + 'locale';
  bindtextdomain('JVCLInstall', Path);
  bindtextdomain('jvcl', Path);
  AddDomainForResourceString('JVCLInstall');
end;

initialization
  InitDxgettext;

{$ENDIF USE_DXGETTEXT}

end.
