{ $Id$ } { /*************************************************************************** diskdiffsdialog.pas - form for showing the diffs of editor files changed on disk ***************************************************************************/ *************************************************************************** * * * This source is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This code is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * General Public License for more details. * * * * A copy of the GNU General Public License is available on the World * * Wide Web at . You can also * * obtain it by writing to the Free Software Foundation, * * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * * *************************************************************************** } unit DiskDiffsDialog; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Buttons, StdCtrls, LResources, Project, SynEdit, LCLType, DiffPatch, LazarusIDEStrConsts, ComCtrls, ExtCtrls; type PDiffItem = ^TDiffItem; TDiffItem = record Valid: boolean; UnitInfo: TUnitInfo; Diff: string; TxtOnDisk: string; end; { TDiskDiffsDlg } TDiskDiffsDlg = class(TForm) DiffSynEdit: TSynEdit; FilesListBox: TListBox; RevertAllButton: TButton; IgnoreDiskChangesButton: TButton; Splitter: TSplitter; procedure DiskDiffsDlgKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); procedure FilesListBoxMouseUp(Sender: TOBject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); private FUnitList: TList; FCachedDiffs: TList; // List of PDiffItem procedure FillFilesListBox; procedure SetUnitList(const AValue: TList); procedure ShowDiff; function GetCachedDiff(AnUnitInfo: TUnitInfo): PDiffItem; procedure ClearCache; public property UnitList: TList read FUnitList write SetUnitList; // list of TUnitInfo constructor Create(TheOwner: TComponent); override; destructor Destroy; override; end; function ShowDiskDiffsDialog(AnUnitList: TList): TModalResult; implementation var DiskDiffsDlg: TDiskDiffsDlg = nil; function ShowDiskDiffsDialog(AnUnitList: TList): TModalResult; begin if DiskDiffsDlg<>nil then begin Result:=mrIgnore; exit; end; DiskDiffsDlg:=TDiskDiffsDlg.Create(nil); DiskDiffsDlg.UnitList:=AnUnitList; Result:=DiskDiffsDlg.ShowModal; DiskDiffsDlg.Free; DiskDiffsDlg:=nil; end; { TDiskDiffsDlg } procedure TDiskDiffsDlg.DiskDiffsDlgKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if Key=VK_Escape then ModalResult:=mrCancel; end; procedure TDiskDiffsDlg.FilesListBoxMouseUp(Sender: TOBject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin ShowDiff; end; procedure TDiskDiffsDlg.FillFilesListBox; var i: integer; begin FilesListBox.Items.BeginUpdate; FilesListBox.Items.Clear; for i:=0 to UnitList.Count-1 do FilesListBox.Items.Add(TUnitInfo(UnitList[i]).ShortFilename); FilesListBox.Items.EndUpdate; end; procedure TDiskDiffsDlg.SetUnitList(const AValue: TList); begin FUnitList:=AValue; FillFilesListBox; end; procedure TDiskDiffsDlg.ShowDiff; var i: integer; DiffItem: PDiffItem; begin i:=FilesListBox.ItemIndex; if i>=0 then begin DiffItem:=GetCachedDiff(TUnitInfo(FUnitList[i])); DiffSynEdit.Lines.Text:=DiffItem^.Diff; end else begin DiffSynEdit.Lines.Clear; end; end; function TDiskDiffsDlg.GetCachedDiff(AnUnitInfo: TUnitInfo): PDiffItem; var i: integer; fs: TFileStream; begin if FCachedDiffs=nil then FCachedDiffs:=TList.Create; for i:=0 to FCachedDiffs.Count-1 do begin Result:=PDiffItem(FCachedDiffs[i]); if (Result<>nil) and (Result^.UnitInfo=AnUnitInfo) then exit; end; New(Result); Result^.UnitInfo:=AnUnitInfo; try fs:=TFileStream.Create(AnUnitInfo.Filename,fmOpenRead); SetLength(Result^.TxtOnDisk,fs.Size); if Result^.TxtOnDisk<>'' then fs.Read(Result^.TxtOnDisk[1],length(Result^.TxtOnDisk)); fs.Free; Result^.Diff:=CreateTextDiff(AnUnitInfo.Source.Source,Result^.TxtOnDisk,[], tdoContext); except On E: Exception do Result^.Diff:='\ '+Format(lisDiskDiffErrorReadingFile, [E.Message]); end; FCachedDiffs.Add(Result); end; procedure TDiskDiffsDlg.ClearCache; var i: integer; DiffItem: PDiffItem; begin if FCachedDiffs=nil then exit; for i:=0 to FCachedDiffs.Count-1 do begin DiffItem:=PDiffItem(FCachedDiffs[i]); if DiffItem<>nil then begin DiffItem^.TxtOnDisk:=''; DiffItem^.Diff:=''; Dispose(DiffItem); end; end; FCachedDiffs.Clear; end; constructor TDiskDiffsDlg.Create(TheOwner: TComponent); begin inherited Create(TheOwner); Caption:=lisDiskDiffSomeFilesHaveChangedOnDisk; DiffSynEdit.Lines.Text:=lisDiskDiffClickOnOneOfTheAboveItemsToSeeTheDiff; RevertAllButton.Caption:=lisDiskDiffRevertAll; IgnoreDiskChangesButton.Caption:=lisDiskDiffIgnoreDiskChanges; end; destructor TDiskDiffsDlg.Destroy; begin ClearCache; FCachedDiffs.Free; inherited Destroy; end; initialization {$I diskdiffsdialog.lrs} end.