NSIS/Contrib/VPatch/Source/GUI/MainForm.pas
kichik 4bf6509225 VPatch 3.0
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@4271 212acab6-be3b-0410-9dea-997c60f758d6
2005-09-17 09:25:44 +00:00

539 lines
14 KiB
ObjectPascal

unit MainForm;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, Buttons, StdCtrls, Menus, PatchClasses, VirtualTrees, VDSP_CRC,
ToolWin, ComCtrls, ImgList, ExtCtrls, Math, OSUtil;
const
UntitledFile='Untitled.vpj';
type
TfrmMain = class(TForm)
MainMenu: TMainMenu;
mnuFile: TMenuItem;
mnuNew: TMenuItem;
mnuOpen: TMenuItem;
mnuSave: TMenuItem;
mnuSaveas: TMenuItem;
N1: TMenuItem;
mnuExit: TMenuItem;
Label1: TLabel;
grpConfig: TGroupBox;
butAdd: TSpeedButton;
OD: TOpenDialog;
Label2: TLabel;
txtNew: TEdit;
Label3: TLabel;
mnuHelp: TMenuItem;
mnuAbout: TMenuItem;
lstOld: TListBox;
butOldAdd: TSpeedButton;
butOldRemove: TSpeedButton;
butNewEdit: TSpeedButton;
Label4: TLabel;
lstNew: TVirtualStringTree;
dlgOpen: TOpenDialog;
dlgSave: TSaveDialog;
IL: TImageList;
mnuAction: TMenuItem;
mnuGenGo: TMenuItem;
barTool: TToolBar;
toolNew: TToolButton;
toolOpen: TToolButton;
toolSave: TToolButton;
toolGenGo: TToolButton;
mnuCreateEXE: TMenuItem;
dlgSaveExe: TSaveDialog;
toolCreateEXE: TToolButton;
barCool: TCoolBar;
Label5: TLabel;
Label7: TLabel;
tbBlockSize: TTrackBar;
txtStartBlockSize: TLabel;
mnuClearcachedpatches: TMenuItem;
mnuCreateDLL: TMenuItem;
mnuCreatePAT: TMenuItem;
toolCreateDLL: TToolButton;
ToolButton1: TToolButton;
toolCreatePAT: TToolButton;
dlgSaveDLL: TSaveDialog;
dlgSavePAT: TSaveDialog;
chkOutputWait: TCheckBox;
mnuWebsite: TMenuItem;
Readme1: TMenuItem;
N2: TMenuItem;
ReadmeincludedwithNSIS1: TMenuItem;
chkOptimal: TCheckBox;
procedure butAddClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure mnuExitClick(Sender: TObject);
procedure UpdateStates;
procedure ReloadNewTree;
procedure SelectInNewTree(PatchIndex: Integer);
procedure butNewEditClick(Sender: TObject);
procedure lstNewChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure butOldAddClick(Sender: TObject);
procedure butOldRemoveClick(Sender: TObject);
procedure mnuNewClick(Sender: TObject);
procedure mnuOpenClick(Sender: TObject);
procedure mnuSaveClick(Sender: TObject);
procedure mnuSaveasClick(Sender: TObject);
procedure mnuGenGoClick(Sender: TObject);
procedure mnuAboutClick(Sender: TObject);
procedure mnuCreateEXEClick(Sender: TObject);
procedure lstNewGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
procedure txtStartBlockSizeChange(Sender: TObject);
procedure txtMinimumBlockSizeChange(Sender: TObject);
procedure txtBlockDividerChange(Sender: TObject);
procedure txtStepSizeChange(Sender: TObject);
procedure tbBlockSizeChange(Sender: TObject);
procedure mnuClearcachedpatchesClick(Sender: TObject);
procedure mnuCreateDLLClick(Sender: TObject);
procedure mnuCreatePATClick(Sender: TObject);
procedure chkOutputWaitClick(Sender: TObject);
procedure mnuWebsiteClick(Sender: TObject);
procedure Readme1Click(Sender: TObject);
procedure ReadmeincludedwithNSIS1Click(Sender: TObject);
procedure chkOptimalClick(Sender: TObject);
private
{ Private declarations }
// MS: TModeSelector;
dskName: String;
function DoSave(const FileName: String; const Prompt: Boolean): String;
procedure OpenAFile(FileName: String; AskSave: Boolean=True; PromptNew: Boolean=False);
function CollectConfig: String;
procedure SetConfigTextBoxes(Config: String);
public
{ Public declarations }
end;
var
frmMain: TfrmMain;
PP: TPatchProject = nil;
implementation
uses AboutForm, DLLWrapper;
{$R *.dfm}
procedure TfrmMain.butAddClick(Sender: TObject);
begin
OD.Options:=OD.Options-[ofAllowMultiSelect];
OD.Title:='Open the latest (new) version of a file...';
OD.FileName:='';
if OD.Execute then begin
PP.AddNewVersion(OD.FileName);
ReloadNewTree;
SelectInNewTree(PP.PatchFile(OD.FileName).Index);
butOldAdd.Click;
end;
end;
procedure TfrmMain.FormCreate(Sender: TObject);
begin
grpConfig.Tag:=-1;
dskName:=UntitledFile;
lstNew.NodeDataSize:=SizeOf(Integer);
OpenAFile('',False,False); //don't prompt for New! that'll bug things
ReloadNewTree;
UpdateStates;
end;
procedure TfrmMain.FormDestroy(Sender: TObject);
begin
PP.Free;
end;
procedure TfrmMain.mnuExitClick(Sender: TObject);
begin
Close;
end;
procedure TfrmMain.UpdateStates;
begin
Self.Caption:='VG - VPatch GUI - '+dskName;
// grpConfig.Enabled:=not (lstNew.Tag=-1);
// if not grpConfig.Enabled then grpConfig.Caption:='Select a file first';
grpConfig.Enabled:=(lstNew.SelectedCount>0);
if grpConfig.Tag=-1 then begin
txtNew.Enabled:=False;
butNewEdit.Enabled:=False;
butNewEdit.Font.Color:=clInactiveCaption;
butOldAdd.Enabled:=False;
butOldAdd.Font.Color:=clInactiveCaption;
butOldRemove.Enabled:=False;
butOldRemove.Font.Color:=clInactiveCaption;
end else begin
txtNew.Enabled:=True;
butNewEdit.Enabled:=True;
butNewEdit.Font.Color:=clWindowText;
butOldAdd.Enabled:=True;
butOldAdd.Font.Color:=clWindowText;
// butOldEdit.Enabled:=True;
butOldRemove.Enabled:=True;
butOldRemove.Font.Color:=clWindowText;
end;
end;
procedure TfrmMain.ReloadNewTree;
var
i: Integer;
Node: PVirtualNode;
begin
lstNew.BeginUpdate;
lstNew.Clear;
for i:=0 to PP.GetPatchCount - 1 do begin
Node:=lstNew.AddChild(nil);
PInteger(lstNew.GetNodeData(Node))^:=i;
end;
lstNew.EndUpdate;
end;
procedure TfrmMain.butNewEditClick(Sender: TObject);
var
i: Integer;
begin
OD.Options:=OD.Options-[ofAllowMultiSelect];
OD.Title:='Select new version of file...';
OD.FileName:=txtNew.Text;
if OD.Execute then begin
i:=grpConfig.Tag;
PP.PatchFile(i).NewVersion:=OD.FileName;
ReloadNewTree;
lstNew.Selected[lstNew.GetFirstVisible]:=True;
end;
end;
procedure TfrmMain.lstNewChange(Sender: TBaseVirtualTree;
Node: PVirtualNode);
var
i,j: Integer;
begin
case lstNew.SelectedCount of
0: Exit;
1: begin
if lstNew.Selected[Node] then begin
i:=PInteger(lstNew.GetNodeData(Node))^;
grpConfig.Caption:=ExtractFileName(PP.PatchFile(i).NewVersion);
grpConfig.Tag:=i;
txtNew.Text:=PP.PatchFile(i).NewVersion;
lstOld.Clear;
for j:=0 to PP.PatchFile(i).OldVersionCount - 1 do begin
lstOld.Items.Add(PP.PatchFile(i).OldVersions[j]);
end;
SetConfigTextBoxes(PP.PatchFile(i).Config);
end;
end;
else begin
grpConfig.Tag:=-1; //multiple files selected - only allow config changes
txtNew.Text:='(multiple files selected)';
lstOld.Clear;
end;
end;
UpdateStates;
end;
procedure TfrmMain.butOldAddClick(Sender: TObject);
var
i,j: Integer;
begin
OD.Options:=OD.Options+[ofAllowMultiSelect];
OD.Title:='Select old versions of '+grpConfig.Caption+'...';
OD.FileName:='';
if OD.Execute then begin
i:=grpConfig.Tag;
for j:=0 to OD.Files.Count - 1 do begin
PP.PatchFile(i).AddOldVersion(OD.Files[j]);
lstOld.Items.Add(OD.Files.Strings[j]);
end;
end;
end;
procedure TfrmMain.SelectInNewTree(PatchIndex: Integer);
var
Node: PVirtualNode;
begin
Node:=lstNew.GetFirstSelected;
while Node<>nil do begin
lstNew.Selected[Node]:=False;
Node:=lstNew.GetNextSelected(Node);
end;
Node:=lstNew.GetFirst;
while Node<>nil do begin
if PInteger(lstNew.GetNodeData(Node))^=PatchIndex then begin
lstNew.Selected[Node]:=True;
lstNewChange(lstNew,Node);
Exit;
end;
Node:=lstNew.GetNext(Node);
end;
end;
procedure TfrmMain.butOldRemoveClick(Sender: TObject);
begin
if lstOld.ItemIndex>=0 then begin
PP.PatchFile(grpConfig.Tag).RemoveOldVersion(lstOld.ItemIndex);
lstOld.Items.Delete(lstOld.ItemIndex);
end;
end;
procedure TfrmMain.OpenAFile(FileName: String; AskSave: Boolean=True; PromptNew: Boolean=False);
var
fs: TFileStream;
begin
PP.Free; //confirm saving first?
PP:=TPatchProject.Create;
ReloadNewTree;
if FileName<>'' then begin
fs:=TFileStream.Create(FileName,fmOpenRead);
try
PP.LoadFromStream(fs);
except
on E: Exception do ShowMessage(E.Message);
end;
dskName:=FileName;
ReloadNewTree;
fs.Free;
end else begin
dskName:=UntitledFile;
if PromptNew then butAddClick(Self);
end;
UpdateStates;
end;
procedure TfrmMain.mnuNewClick(Sender: TObject);
begin
OpenAFile('',True,True);
end;
procedure TfrmMain.mnuOpenClick(Sender: TObject);
begin
if dlgOpen.Execute then begin
OpenAFile(dlgOpen.FileName,True);
if lstNew.GetFirst <> nil then
lstNew.Selected[lstNew.GetFirst]:=True;
end;
end;
procedure TfrmMain.mnuSaveClick(Sender: TObject);
begin
dskName:=DoSave(dskName,False);
UpdateStates;
end;
procedure TfrmMain.mnuSaveasClick(Sender: TObject);
begin
dskName:=DoSave(dskName,True);
UpdateStates;
end;
function TfrmMain.DoSave(const FileName: String; const Prompt: Boolean): String;
var
FN: String;
fs: TFileStream;
begin
DoSave:='';
FN:=FileName;
if Prompt or (CompareText(FileName,UntitledFile)=0) then begin
if dlgSave.Execute then begin
FN:=dlgSave.FileName;
if ExtractFileExt(FN)='' then
FN:=FN+'.vpj';
end else begin
DoSave:=FileName;
Exit;
end;
end;
//do actual saving to this file...
fs:=TFileStream.Create(FN,fmCreate);
PP.SaveToStream(fs);
fs.Free;
DoSave:=FN;
end;
procedure TfrmMain.mnuGenGoClick(Sender: TObject);
begin
Self.Visible:=False;
Cursor:=crHourGlass;
PP.Generate;
Cursor:=crDefault;
Self.Visible:=True;
SelectInNewTree(0);
end;
procedure TfrmMain.mnuAboutClick(Sender: TObject);
var
frmAbout: TfrmAbout;
begin
frmAbout:=TfrmAbout.Create(Self);
frmAbout.ShowModal;
frmAbout.Free;
end;
procedure TfrmMain.mnuCreateEXEClick(Sender: TObject);
var
fs: TFileStream;
fr: TFileStream;
begin
//first, select it on disk (where should the exe go?)
if dlgSaveExe.FileName='' then dlgSaveExe.FileName:='VPatch.exe';
if dlgSaveExe.Execute then begin
fs:=nil;
try
fs:=TFileStream.Create(dlgSaveExe.FileName,fmCreate);
fr:=nil;
try
fr:=TFileStream.Create(ExtractFilePath(Application.ExeName)+'vpatch.bin',fmOpenRead);
fs.CopyFrom(fr,fr.Size);
finally
fr.Free;
end;
PP.WritePatches(fs);
finally
fs.Free;
end;
end;
end;
procedure TfrmMain.mnuCreateDLLClick(Sender: TObject);
var
fs: TFileStream;
fr: TFileStream;
begin
//first, select it on disk (where should the exe go?)
if dlgSaveDLL.FileName='' then dlgSaveDLL.FileName:='VPatch.DLL';
if dlgSaveDLL.Execute then begin
fs:=nil;
try
fs:=TFileStream.Create(dlgSaveDLL.FileName,fmCreate);
fr:=nil;
try
fr:=TFileStream.Create(ExtractFilePath(Application.ExeName)+'vpatchdll.bin',fmOpenRead);
fs.CopyFrom(fr,fr.Size);
finally
fr.Free;
end;
PP.WritePatches(fs);
finally
fs.Free;
end;
end;
end;
procedure TfrmMain.mnuCreatePATClick(Sender: TObject);
var
fs: TFileStream;
begin
//first, select it on disk (where should the exe go?)
if dlgSavePAT.FileName='' then dlgSavePAT.FileName:='PatchData.pat';
if dlgSavePAT.Execute then begin
fs:=nil;
try
fs:=TFileStream.Create(dlgSavePAT.FileName,fmCreate);
PP.WritePatches(fs);
finally
fs.Free;
end;
end;
end;
procedure TfrmMain.lstNewGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
var
i: Integer;
begin
i:=PInteger(lstNew.GetNodeData(Node))^;
CellText:=ExtractFileName(PP.PatchFile(i).NewVersion);
end;
procedure TfrmMain.txtStartBlockSizeChange(Sender: TObject);
begin
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
end;
function TfrmMain.CollectConfig: String;
begin
Result:=txtStartBlockSize.Caption;
end;
procedure TfrmMain.txtMinimumBlockSizeChange(Sender: TObject);
begin
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
end;
procedure TfrmMain.txtBlockDividerChange(Sender: TObject);
begin
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
end;
procedure TfrmMain.txtStepSizeChange(Sender: TObject);
begin
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
end;
procedure TfrmMain.SetConfigTextBoxes(Config: String);
var
a,i: Integer;
begin
a:=Pos(',',Config);
if(a=0) then a:=Length(Config)+1;
txtStartBlockSize.Caption:=Copy(Config,1,a-1);
Config:=Copy(Config,a+1,Length(Config));
a:=StrToInt(txtStartBlockSize.Caption);
i:=-1;
while not (a=0) do begin
a:=a shr 1;
Inc(i);
end;
tbBlockSize.Position := i;
end;
procedure TfrmMain.tbBlockSizeChange(Sender: TObject);
begin
txtStartBlockSize.Caption:=IntToStr(1 shl tbBlockSize.Position);
PP.PatchFile(grpConfig.Tag).Config:=CollectConfig;
end;
procedure TfrmMain.mnuClearcachedpatchesClick(Sender: TObject);
begin
PP.ResetCache;
end;
procedure TfrmMain.chkOutputWaitClick(Sender: TObject);
begin
WaitAfterGenerate:=chkOutputWait.Checked;
end;
procedure TfrmMain.mnuWebsiteClick(Sender: TObject);
begin
OpenLink('http://www.tibed.net/vpatch');
end;
procedure TfrmMain.Readme1Click(Sender: TObject);
begin
OpenLink('VPatch.htm');
end;
procedure TfrmMain.ReadmeincludedwithNSIS1Click(Sender: TObject);
begin
OpenLink('Readme.html');
end;
procedure TfrmMain.chkOptimalClick(Sender: TObject);
begin
OptimalPatches:=chkOptimal.Checked;
end;
initialization
PP:=TPatchProject.Create;
end.