| 1 | unit FormCompareSideBySide;
|
|---|
| 2 |
|
|---|
| 3 | interface
|
|---|
| 4 |
|
|---|
| 5 | uses
|
|---|
| 6 | Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,
|
|---|
| 7 | VCard, Diff, LCLType, LCLIntf, ComCtrls, Buttons, Menus, ActnList, SynEdit,
|
|---|
| 8 | SynEditMiscClasses, SynHighlighterPosition, SynEditHighlighter, Common,
|
|---|
| 9 | SynEditEx, FormEx;
|
|---|
| 10 |
|
|---|
| 11 | type
|
|---|
| 12 |
|
|---|
| 13 | { TFormCompareSideBySide }
|
|---|
| 14 |
|
|---|
| 15 | TFormCompareSideBySide = class(TFormEx)
|
|---|
| 16 | ASwitchSides: TAction;
|
|---|
| 17 | AReloadFiles: TAction;
|
|---|
| 18 | AFileOpenLeft: TAction;
|
|---|
| 19 | AFileOpenRight: TAction;
|
|---|
| 20 | ActionList1: TActionList;
|
|---|
| 21 | EditLeftFileName: TEdit;
|
|---|
| 22 | EditRightFileName: TEdit;
|
|---|
| 23 | MainMenu1: TMainMenu;
|
|---|
| 24 | MenuItem1: TMenuItem;
|
|---|
| 25 | MenuItem2: TMenuItem;
|
|---|
| 26 | MenuItem3: TMenuItem;
|
|---|
| 27 | MenuItem4: TMenuItem;
|
|---|
| 28 | MenuItem5: TMenuItem;
|
|---|
| 29 | MenuItemClose: TMenuItem;
|
|---|
| 30 | OpenDialogSide: TOpenDialog;
|
|---|
| 31 | PanelLeft: TPanel;
|
|---|
| 32 | PanelRight: TPanel;
|
|---|
| 33 | SpeedButtonOpenLeft: TSpeedButton;
|
|---|
| 34 | SpeedButtonOpenRight: TSpeedButton;
|
|---|
| 35 | Splitter1: TSplitter;
|
|---|
| 36 | SynEditLeft: TSynEditEx;
|
|---|
| 37 | SynEditRight: TSynEditEx;
|
|---|
| 38 | procedure AFileOpenLeftExecute(Sender: TObject);
|
|---|
| 39 | procedure AFileOpenRightExecute(Sender: TObject);
|
|---|
| 40 | procedure AReloadFilesExecute(Sender: TObject);
|
|---|
| 41 | procedure ASwitchSidesExecute(Sender: TObject);
|
|---|
| 42 | procedure FormActivate(Sender: TObject);
|
|---|
| 43 | procedure FormCreate(Sender: TObject);
|
|---|
| 44 | procedure FormDestroy(Sender: TObject);
|
|---|
| 45 | procedure FormResize(Sender: TObject);
|
|---|
| 46 | procedure FormShow(Sender: TObject);
|
|---|
| 47 | procedure MenuItemCloseClick(Sender: TObject);
|
|---|
| 48 | procedure SynEditLeftChange(Sender: TObject);
|
|---|
| 49 | procedure SynEditLeftScroll(Sender: TObject);
|
|---|
| 50 | procedure SynEditRightChange(Sender: TObject);
|
|---|
| 51 | procedure SynEditRightScroll(Sender: TObject);
|
|---|
| 52 | private
|
|---|
| 53 | FLeftSide: string;
|
|---|
| 54 | FRightSide: string;
|
|---|
| 55 | Diff: TDiff;
|
|---|
| 56 | HighlighterLeft: TSynPositionHighlighter;
|
|---|
| 57 | HighlighterRight: TSynPositionHighlighter;
|
|---|
| 58 | AttrAdded: TtkTokenKind;
|
|---|
| 59 | AttrDeleted: TtkTokenKind;
|
|---|
| 60 | AttrModified: TtkTokenKind;
|
|---|
| 61 | LastWidth: Integer;
|
|---|
| 62 | procedure SetLeftSide(AValue: string);
|
|---|
| 63 | procedure SetRightSide(AValue: string);
|
|---|
| 64 | procedure ReloadContent;
|
|---|
| 65 | procedure UpdateInterface;
|
|---|
| 66 | procedure UpdateHighlight;
|
|---|
| 67 | function LoadFile(AFileName: string): string;
|
|---|
| 68 | public
|
|---|
| 69 | procedure LoadFileLeft(FileName: string);
|
|---|
| 70 | procedure LoadFileRight(FileName: string);
|
|---|
| 71 | property LeftSide: string read FLeftSide write SetLeftSide;
|
|---|
| 72 | property RightSide: string read FRightSide write SetRightSide;
|
|---|
| 73 | end;
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 | implementation
|
|---|
| 77 |
|
|---|
| 78 | {$R *.lfm}
|
|---|
| 79 |
|
|---|
| 80 | uses
|
|---|
| 81 | VCardFile;
|
|---|
| 82 |
|
|---|
| 83 | { TFormCompareSideBySide }
|
|---|
| 84 |
|
|---|
| 85 | procedure TFormCompareSideBySide.ASwitchSidesExecute(Sender: TObject);
|
|---|
| 86 | var
|
|---|
| 87 | TempFileName: string;
|
|---|
| 88 | TempContent: string;
|
|---|
| 89 | begin
|
|---|
| 90 | TempContent := SynEditLeft.Text;
|
|---|
| 91 | SynEditLeft.Text := SynEditRight.Text;
|
|---|
| 92 | SynEditRight.Text := TempContent;
|
|---|
| 93 |
|
|---|
| 94 | TempFileName := EditLeftFileName.Text;
|
|---|
| 95 | EditLeftFileName.Text := EditRightFileName.Text;
|
|---|
| 96 | EditRightFileName.Text := TempFileName;
|
|---|
| 97 |
|
|---|
| 98 | UpdateInterface;
|
|---|
| 99 | UpdateHighlight;
|
|---|
| 100 | end;
|
|---|
| 101 |
|
|---|
| 102 | procedure TFormCompareSideBySide.FormActivate(Sender: TObject);
|
|---|
| 103 | begin
|
|---|
| 104 | if LastWidth = -1 then LastWidth := Width;
|
|---|
| 105 | end;
|
|---|
| 106 |
|
|---|
| 107 | procedure TFormCompareSideBySide.AReloadFilesExecute(Sender: TObject);
|
|---|
| 108 | begin
|
|---|
| 109 | LoadFileLeft(EditLeftFileName.Text);
|
|---|
| 110 | LoadFileRight(EditRightFileName.Text);
|
|---|
| 111 | UpdateHighlight;
|
|---|
| 112 | UpdateInterface;
|
|---|
| 113 | end;
|
|---|
| 114 |
|
|---|
| 115 | procedure TFormCompareSideBySide.AFileOpenLeftExecute(Sender: TObject);
|
|---|
| 116 | begin
|
|---|
| 117 | OpenDialogSide.InitialDir := ExtractFileDir(EditLeftFileName.Text);
|
|---|
| 118 | OpenDialogSide.FileName := ExtractFileName(EditLeftFileName.Text);
|
|---|
| 119 | if OpenDialogSide.Execute then begin
|
|---|
| 120 | EditLeftFileName.Text := OpenDialogSide.FileName;
|
|---|
| 121 | SynEditLeft.Text := LoadFileToStr(OpenDialogSide.FileName);
|
|---|
| 122 | end;
|
|---|
| 123 | end;
|
|---|
| 124 |
|
|---|
| 125 | procedure TFormCompareSideBySide.AFileOpenRightExecute(Sender: TObject);
|
|---|
| 126 | begin
|
|---|
| 127 | OpenDialogSide.InitialDir := ExtractFileDir(EditRightFileName.Text);
|
|---|
| 128 | OpenDialogSide.FileName := ExtractFileName(EditRightFileName.Text);
|
|---|
| 129 | if OpenDialogSide.Execute then begin
|
|---|
| 130 | EditRightFileName.Text := OpenDialogSide.FileName;
|
|---|
| 131 | SynEditRight.Text := LoadFileToStr(OpenDialogSide.FileName);
|
|---|
| 132 | end;
|
|---|
| 133 | UpdateHighlight;
|
|---|
| 134 | end;
|
|---|
| 135 |
|
|---|
| 136 | procedure TFormCompareSideBySide.FormCreate(Sender: TObject);
|
|---|
| 137 | begin
|
|---|
| 138 | Diff := TDiff.Create(Self);
|
|---|
| 139 |
|
|---|
| 140 | HighlighterLeft := TSynPositionHighlighter.Create(Self);
|
|---|
| 141 | with HighlighterLeft do begin
|
|---|
| 142 | AttrAdded := CreateTokenID('Added', clNone, clLightGreen, []);
|
|---|
| 143 | AttrDeleted := CreateTokenID('Deleted', clNone, clLightBlue, []);
|
|---|
| 144 | AttrModified := CreateTokenID('Modified', clNone, clLightRed, []);
|
|---|
| 145 | end;
|
|---|
| 146 | SynEditLeft.Highlighter := HighlighterLeft;
|
|---|
| 147 |
|
|---|
| 148 | HighlighterRight := TSynPositionHighlighter.Create(Self);
|
|---|
| 149 | with HighlighterRight do begin
|
|---|
| 150 | AttrAdded := CreateTokenID('Added', clNone, clLightGreen, []);
|
|---|
| 151 | AttrDeleted := CreateTokenID('Deleted', clNone, clLightBlue, []);
|
|---|
| 152 | AttrModified := CreateTokenID('Modified', clNone, clLightRed, []);
|
|---|
| 153 | end;
|
|---|
| 154 | SynEditRight.Highlighter := HighlighterRight;
|
|---|
| 155 |
|
|---|
| 156 | LastWidth := -1;
|
|---|
| 157 | end;
|
|---|
| 158 |
|
|---|
| 159 | procedure TFormCompareSideBySide.FormDestroy(Sender: TObject);
|
|---|
| 160 | begin
|
|---|
| 161 | FreeAndNil(HighlighterLeft);
|
|---|
| 162 | FreeAndNil(HighlighterRight);
|
|---|
| 163 | FreeAndNil(Diff);
|
|---|
| 164 | end;
|
|---|
| 165 |
|
|---|
| 166 | procedure TFormCompareSideBySide.FormResize(Sender: TObject);
|
|---|
| 167 | var
|
|---|
| 168 | LastHandler: TNotifyEvent;
|
|---|
| 169 | NewPanelWidth: Integer;
|
|---|
| 170 | const
|
|---|
| 171 | MaxRatio = 0.8;
|
|---|
| 172 | begin
|
|---|
| 173 | if LastWidth <> -1 then begin
|
|---|
| 174 | LastHandler := PanelLeft.OnResize;
|
|---|
| 175 | try
|
|---|
| 176 | PanelLeft.OnResize := nil;
|
|---|
| 177 | NewPanelWidth := Round((PanelLeft.Width / LastWidth) * Width);
|
|---|
| 178 | if NewPanelWidth > Round(Width * MaxRatio) then NewPanelWidth := Round(Width * MaxRatio);
|
|---|
| 179 | PanelLeft.Width := NewPanelWidth;
|
|---|
| 180 | finally
|
|---|
| 181 | PanelLeft.OnResize := LastHandler;
|
|---|
| 182 | end;
|
|---|
| 183 | LastWidth := Width;
|
|---|
| 184 | end;
|
|---|
| 185 | end;
|
|---|
| 186 |
|
|---|
| 187 | procedure TFormCompareSideBySide.FormShow(Sender: TObject);
|
|---|
| 188 | begin
|
|---|
| 189 | UpdateInterface;
|
|---|
| 190 | ReloadContent;
|
|---|
| 191 | end;
|
|---|
| 192 |
|
|---|
| 193 | procedure TFormCompareSideBySide.MenuItemCloseClick(Sender: TObject);
|
|---|
| 194 | begin
|
|---|
| 195 | Close;
|
|---|
| 196 | end;
|
|---|
| 197 |
|
|---|
| 198 | procedure TFormCompareSideBySide.SynEditLeftChange(Sender: TObject);
|
|---|
| 199 | begin
|
|---|
| 200 | UpdateHighlight;
|
|---|
| 201 | end;
|
|---|
| 202 |
|
|---|
| 203 | procedure TFormCompareSideBySide.SynEditLeftScroll(Sender: TObject);
|
|---|
| 204 | begin
|
|---|
| 205 | SynEditRight.TopLine := SynEditLeft.TopLine;
|
|---|
| 206 | end;
|
|---|
| 207 |
|
|---|
| 208 | procedure TFormCompareSideBySide.SynEditRightChange(Sender: TObject);
|
|---|
| 209 | begin
|
|---|
| 210 | UpdateHighlight;
|
|---|
| 211 | end;
|
|---|
| 212 |
|
|---|
| 213 | procedure TFormCompareSideBySide.SynEditRightScroll(Sender: TObject);
|
|---|
| 214 | begin
|
|---|
| 215 | SynEditLeft.TopLine := SynEditRight.TopLine;
|
|---|
| 216 | end;
|
|---|
| 217 |
|
|---|
| 218 | procedure TFormCompareSideBySide.SetLeftSide(AValue: string);
|
|---|
| 219 | begin
|
|---|
| 220 | if FLeftSide = AValue then Exit;
|
|---|
| 221 | FLeftSide := AValue;
|
|---|
| 222 | end;
|
|---|
| 223 |
|
|---|
| 224 | procedure TFormCompareSideBySide.SetRightSide(AValue: string);
|
|---|
| 225 | begin
|
|---|
| 226 | if FRightSide = AValue then Exit;
|
|---|
| 227 | FRightSide := AValue;
|
|---|
| 228 | end;
|
|---|
| 229 |
|
|---|
| 230 | procedure TFormCompareSideBySide.ReloadContent;
|
|---|
| 231 | begin
|
|---|
| 232 | UpdateHighlight;
|
|---|
| 233 | end;
|
|---|
| 234 |
|
|---|
| 235 | procedure TFormCompareSideBySide.UpdateInterface;
|
|---|
| 236 | begin
|
|---|
| 237 | end;
|
|---|
| 238 |
|
|---|
| 239 | procedure TFormCompareSideBySide.UpdateHighlight;
|
|---|
| 240 | var
|
|---|
| 241 | LeftText: string;
|
|---|
| 242 | RightText: string;
|
|---|
| 243 | I: Integer;
|
|---|
| 244 | LastKind: TChangeKind;
|
|---|
| 245 | P1: TPoint;
|
|---|
| 246 | P2: TPoint;
|
|---|
| 247 | Rec: TCompareRec;
|
|---|
| 248 | NextToken1: TtkTokenKind;
|
|---|
| 249 | NextToken2: TtkTokenKind;
|
|---|
| 250 | begin
|
|---|
| 251 | LeftText := SynEditLeft.Lines.Text;
|
|---|
| 252 | RightText := SynEditRight.Lines.Text;
|
|---|
| 253 |
|
|---|
| 254 | Diff.Execute(PChar(LeftText), PChar(RightText), Length(LeftText), Length(RightText));
|
|---|
| 255 |
|
|---|
| 256 | HighlighterLeft.ClearAllTokens;
|
|---|
| 257 | HighlighterRight.ClearAllTokens;
|
|---|
| 258 | LeftText := '';
|
|---|
| 259 | RightText := '';
|
|---|
| 260 | LastKind := ckNone;
|
|---|
| 261 | P1 := Point(1, 0);
|
|---|
| 262 | P2 := Point(1, 0);
|
|---|
| 263 | NextToken1 := tkText;
|
|---|
| 264 | NextToken2 := tkText;
|
|---|
| 265 | for I := 0 to Diff.Count - 1 do
|
|---|
| 266 | with Diff.Compares[I] do begin
|
|---|
| 267 | Rec := Diff.Compares[I];
|
|---|
| 268 | if Rec.Chr1 = LineEnding then begin
|
|---|
| 269 | if NextToken1 <> tkText then begin
|
|---|
| 270 | HighlighterLeft.AddToken(P1.Y, 0, NextToken1);
|
|---|
| 271 | NextToken1 := tkText;
|
|---|
| 272 | end;
|
|---|
| 273 | Inc(P1.Y);
|
|---|
| 274 | P1.X := 0;
|
|---|
| 275 | LeftText := LeftText + Rec.Chr1;
|
|---|
| 276 | end else begin
|
|---|
| 277 | if Kind = ckAdd then LeftText := LeftText + ' '
|
|---|
| 278 | else LeftText := LeftText + Rec.chr1;
|
|---|
| 279 | if Kind <> LastKind then begin
|
|---|
| 280 | HighlighterLeft.AddToken(P1.Y, P1.X, NextToken1);
|
|---|
| 281 | if Kind = ckNone then NextToken1 := tkText
|
|---|
| 282 | //else if Kind = ckAdd then NextToken1 := AttrAdded
|
|---|
| 283 | else if Kind = ckDelete then NextToken1 := AttrDeleted
|
|---|
| 284 | else if Kind = ckModify then NextToken1 := AttrModified;
|
|---|
| 285 | end;
|
|---|
| 286 | Inc(P1.X);
|
|---|
| 287 | end;
|
|---|
| 288 |
|
|---|
| 289 | if Rec.Chr2 = LineEnding then begin
|
|---|
| 290 | if NextToken2 <> tkText then begin
|
|---|
| 291 | HighlighterRight.AddToken(P2.Y, 0, NextToken2);
|
|---|
| 292 | NextToken2 := tkText;
|
|---|
| 293 | end;
|
|---|
| 294 | Inc(P2.Y);
|
|---|
| 295 | P2.X := 0;
|
|---|
| 296 | RightText := RightText + Rec.Chr2;
|
|---|
| 297 | end else begin
|
|---|
| 298 | if Kind = ckDelete then RightText := RightText + ' '
|
|---|
| 299 | else RightText := RightText + Rec.Chr2;
|
|---|
| 300 | if Kind <> LastKind then begin
|
|---|
| 301 | HighlighterRight.AddToken(P2.Y, P2.X, NextToken2);
|
|---|
| 302 | if Kind = ckNone then NextToken2 := tkText
|
|---|
| 303 | else if Kind = ckAdd then NextToken2 := AttrAdded
|
|---|
| 304 | //else if Kind = ckDelete then NextToken2 := AttrDeleted
|
|---|
| 305 | else if Kind = ckModify then NextToken2 := AttrModified;
|
|---|
| 306 | end;
|
|---|
| 307 | Inc(P2.X);
|
|---|
| 308 | end;
|
|---|
| 309 |
|
|---|
| 310 | LastKind := Kind;
|
|---|
| 311 | end;
|
|---|
| 312 |
|
|---|
| 313 | //SynEditLeft.Lines.Text := LeftText;
|
|---|
| 314 | //SynEditRight.Lines.Text := RightText;
|
|---|
| 315 | end;
|
|---|
| 316 |
|
|---|
| 317 | function TFormCompareSideBySide.LoadFile(AFileName: string): string;
|
|---|
| 318 | var
|
|---|
| 319 | Ext: string;
|
|---|
| 320 | begin
|
|---|
| 321 | Ext := ExtractFileExt(AFileName);
|
|---|
| 322 | if Ext = VCardFileExt then begin
|
|---|
| 323 | with TVCardFile.Create(nil) do
|
|---|
| 324 | try
|
|---|
| 325 | LoadFromFile(AFileName);
|
|---|
| 326 | Result := VCard.AsString;
|
|---|
| 327 | finally
|
|---|
| 328 | Free;
|
|---|
| 329 | end;
|
|---|
| 330 | end else Result := LoadFileToStr(AFileName);
|
|---|
| 331 | end;
|
|---|
| 332 |
|
|---|
| 333 | procedure TFormCompareSideBySide.LoadFileLeft(FileName: string);
|
|---|
| 334 | begin
|
|---|
| 335 | EditLeftFileName.Text := FileName;
|
|---|
| 336 | LeftSide := LoadFile(FileName);
|
|---|
| 337 | SynEditLeft.Text := LeftSide;
|
|---|
| 338 | end;
|
|---|
| 339 |
|
|---|
| 340 | procedure TFormCompareSideBySide.LoadFileRight(FileName: string);
|
|---|
| 341 | begin
|
|---|
| 342 | EditRightFileName.Text := FileName;
|
|---|
| 343 | RightSide := LoadFile(FileName);
|
|---|
| 344 | SynEditRight.Text := RightSide;
|
|---|
| 345 | end;
|
|---|
| 346 |
|
|---|
| 347 | end.
|
|---|
| 348 |
|
|---|