36
Classes, SysUtils, Math, LCLProc, Forms, Controls, Grids, LResources,
36
Classes, SysUtils, Math, LCLProc, Forms, Controls, Grids, LResources, LConvEncoding,
37
37
Graphics, Dialogs, Buttons, StdCtrls, ExtCtrls, contnrs, FileUtil,
39
39
SynHighlighterLFM, SynEdit, SynEditMiscClasses, LFMTrees,
44
44
CustomFormEditor, LazarusIDEStrConsts, IDEProcs, OutputFilter,
45
45
EditorOptions, CheckLFMDlg, IDEMsgIntf,
47
ConverterTypes, ConvertSettings, ReplaceNamesUnit, ConvCodeTool;
47
ConverterTypes, ConvertSettings, ReplaceNamesUnit,
48
ConvCodeTool, FormFileConv, UsedUnits;
54
55
TDFMConverter = class
56
57
fOrigFormat: TLRSStreamOriginalFormat;
58
fIDEMsgWindow: TIDEMessagesWindowInterface;
57
59
function GetLFMFilename(const DfmFilename: string; KeepCase: boolean): string;
62
constructor Create(aIDEMsgWindow: TIDEMessagesWindowInterface);
61
63
destructor Destroy; override;
62
function ConvertDfmToLfm(const DfmFilename: string): TModalResult;
64
function ConvertDfmToLfm(const aFilename: string): TModalResult;
63
65
function Convert(const DfmFilename: string): TModalResult;
77
80
fTypeReplaceGrid: TStringGrid;
78
81
function ReplaceAndRemoveAll: TModalResult;
79
82
function ReplaceTopOffsets(aSrcOffsets: TList): TModalResult;
83
function AddNewProps(aNewProps: TList): TModalResult;
80
84
// Fill StringGrids with missing properties and types from fLFMTree.
81
85
procedure FillReplaceGrids;
128
function ConvertDfmToLfm(const DfmFilename: string): TModalResult;
135
function ConvertDfmToLfm(const DfmFilename: string): TModalResult;
137
DFMConverter: TDFMConverter;
139
DFMConverter:=TDFMConverter.Create;
140
try Result:=DFMConverter.ConvertDfmToLfm(DfmFilename);
141
finally DFMConverter.Free;
145
137
function IsMissingType(LFMError: TLFMError): boolean;
165
158
function TDFMConverter.Convert(const DfmFilename: string): TModalResult;
167
162
Result:=ConvertDfmToLfm(DfmFilename);
168
163
if Result=mrOK then begin
169
164
if fOrigFormat=sofBinary then
170
ShowMessage(Format('File %s is successfully converted to text format.',
173
ShowMessage(Format('File %s syntax is correct.', [DfmFilename]));
165
s:=Format('File %s is converted to text format.', [DfmFilename]);
166
if Assigned(fIDEMsgWindow) then
167
IDEMessagesWindow.AddMsg(s, '', -1)
170
s:=Format('File %s syntax is correct.', [DfmFilename]);
198
197
// Note: The file is copied from DFM file earlier.
200
DFMStream.LoadFromFile(UTF8ToSys(DfmFilename));
199
DFMStream.LoadFromFile(UTF8ToSys(aFilename));
202
201
on E: Exception do begin
203
202
Result:=QuestionDlg(lisCodeToolsDefsReadError, Format(
204
lisUnableToReadFileError, ['"', DfmFilename, '"', #13, E.Message]),
203
lisUnableToReadFileError, ['"', aFilename, '"', #13, E.Message]),
205
204
mtError,[mrIgnore,mrAbort],0);
206
205
if Result=mrIgnore then // The caller will continue like nothing happened.
215
214
on E: Exception do begin
216
215
Result:=QuestionDlg(lisFormatError,
217
Format(lisUnableToConvertFileError, ['"',DfmFilename,'"',#13,E.Message]),
216
Format(lisUnableToConvertFileError, ['"',aFilename,'"',#13,E.Message]),
218
217
mtError,[mrIgnore,mrAbort],0);
219
218
if Result=mrIgnore then
224
223
// converting dfm file, without renaming unit -> keep case...
226
LFMStream.SaveToFile(UTF8ToSys(DfmFilename));
225
LFMStream.SaveToFile(UTF8ToSys(aFilename));
228
227
on E: Exception do begin
229
228
Result:=MessageDlg(lisCodeToolsDefsWriteError,
230
Format(lisUnableToWriteFileError, ['"',DfmFilename,'"',#13,E.Message]),
229
Format(lisUnableToWriteFileError, ['"',aFilename,'"',#13,E.Message]),
231
230
mtError,[mbIgnore,mbAbort],0);
232
231
if Result=mrIgnore then
298
297
AddReplacement(ChgEntryRepl,StartPos,EndPos,NewIdent);
299
298
IDEMessagesWindow.AddMsg(Format(
300
299
'Replaced type "%s" with "%s".',[OldIdent, NewIdent]),'',-1);
300
if Assigned(fUsedUnitsTool) then begin
301
// ToDo: This is a test and will be replaced by configurable unit names.
302
if NewIdent='TRichMemo' then
303
fUsedUnitsTool.AddUnitIfNeeded('RichMemo');
341
345
function TLFMFixer.ReplaceTopOffsets(aSrcOffsets: TList): TModalResult;
342
346
// Replace top coordinates of controls in visual containers.
343
// Returns mrOK if no types were changed, and mrCancel if there was an error.
345
348
TopOffs: TSrcPropOffset;
346
349
VisOffs: TVisualOffset;
347
OldNum, Ofs, NewNum, Len, ind, i: integer;
350
OldNum, NewNum, Len, ind, i: integer;
350
353
// Add offset to top coordinates.
351
for i := aSrcOffsets.Count-1 downto 0 do begin
354
for i:=aSrcOffsets.Count-1 downto 0 do begin
352
355
TopOffs:=TSrcPropOffset(aSrcOffsets[i]);
353
356
if fSettings.CoordOffsets.Find(TopOffs.ParentType, ind) then begin
354
357
VisOffs:=fSettings.CoordOffsets[ind];
376
function TLFMFixer.AddNewProps(aNewProps: TList): TModalResult;
377
// Add new property to the lfm file.
379
Entry: TAddPropEntry;
383
for i:=aNewProps.Count-1 downto 0 do begin
384
Entry:=TAddPropEntry(aNewProps[i]);
385
fLFMBuffer.Replace(Entry.StartPos, Entry.EndPos-Entry.StartPos,Entry.NewText);
386
IDEMessagesWindow.AddMsg(Format('Added property "%s" for %s.',
387
[Entry.NewText, Entry.ParentType]),'',-1);
374
391
procedure TLFMFixer.FillReplaceGrids;
376
393
PropUpdater: TGridUpdater;
393
410
if NewIdent<>'' then
394
411
fHasMissingObjectTypes:=true;
396
else if fSettings.UnknownPropsMode<>rlDisabled then begin
413
else if fSettings.PropReplaceMode<>rlDisabled then begin
397
414
OldIdent:=CurError.Node.GetIdentifier;
398
415
PropUpdater.AddUnique(OldIdent); // Add each property only once.
399
416
fHasMissingProperties:=true;
426
443
fPropReplaceGrid:=FixLFMDialog.PropReplaceGrid;
427
444
fTypeReplaceGrid:=FixLFMDialog.TypeReplaceGrid;
429
if ((fSettings.UnknownPropsMode=rlAutomatic) or not fHasMissingProperties)
430
and not fHasMissingObjectTypes then
446
if ((fSettings.PropReplaceMode=rlAutomatic) or not fHasMissingProperties)
447
and ((fSettings.TypeReplaceMode=raAutomatic) or not fHasMissingObjectTypes) then
431
448
Result:=ReplaceAndRemoveAll // Can return mrRetry.
433
450
// Cursor is earlier set to HourGlass. Show normal cursor while in dialog.
447
464
function TLFMFixer.Repair: TModalResult;
449
466
ConvTool: TConvDelphiCodeTool;
450
ValueTreeNodes: TObjectList;
467
FormFileTool: TFormFileConverter;
468
SrcCoordOffs: TObjectList;
469
SrcNewProps: TObjectList;
451
470
LoopCount: integer;
453
472
Result:=mrCancel;
455
474
if not fLFMTree.ParseIfNeeded then exit;
456
475
// Change a type that main form inherits from to a fall-back type if needed.
457
476
ConvTool:=TConvDelphiCodeTool.Create(fCTLink);
458
ValueTreeNodes:=TObjectList.Create;
460
478
if not ConvTool.FixMainClassAncestor(TLFMObjectNode(fLFMTree.Root).TypeName,
461
479
fSettings.ReplaceTypes) then exit;
464
if CodeToolBoss.CheckLFM(fPascalBuffer,fLFMBuffer,fLFMTree,
465
fRootMustBeClassInUnit,fRootMustBeClassInIntf,fObjectsMustExists) then
467
else // Rename/remove properties and types interactively.
468
Result:=ShowRepairLFMWizard; // Can return mrRetry.
470
until (Result in [mrOK, mrCancel]) or (LoopCount=10);
471
// Show remaining errors to user.
473
if (Result=mrOK) and (fSettings.CoordOffsMode=rsEnabled) then begin
474
// Fix top offsets of some components in visual containers
475
if ConvTool.CheckTopOffsets(fLFMBuffer, fLFMTree,
476
fSettings.CoordOffsets, ValueTreeNodes) then
477
Result:=ReplaceTopOffsets(ValueTreeNodes)
485
if CodeToolBoss.CheckLFM(fPascalBuffer,fLFMBuffer,fLFMTree,
486
fRootMustBeClassInUnit,fRootMustBeClassInIntf,fObjectsMustExist) then
488
else // Rename/remove properties and types interactively.
489
Result:=ShowRepairLFMWizard; // Can return mrRetry.
491
until (Result in [mrOK, mrCancel]) or (LoopCount=10);
492
// Show remaining errors to user.
494
if (Result=mrOK) and (fSettings.CoordOffsMode=rsEnabled) then begin
495
// Fix top offsets of some components in visual containers
496
FormFileTool:=TFormFileConverter.Create(fCTLink, fLFMBuffer);
497
SrcCoordOffs:=TObjectList.Create;
498
SrcNewProps:=TObjectList.Create;
500
FormFileTool.VisOffsets:=fSettings.CoordOffsets;
501
FormFileTool.SrcCoordOffs:=SrcCoordOffs;
502
FormFileTool.SrcNewProps:=SrcNewProps;
503
Result:=FormFileTool.Convert;
504
if Result=mrOK then begin
505
Result:=ReplaceTopOffsets(SrcCoordOffs);
507
Result:=AddNewProps(SrcNewProps);
507
537
Caption:=lisFixLFMFile;
508
538
Position:=poScreenCenter;
509
// IDEDialogLayoutList.ApplyLayout(Self,600,400);
510
539
NoteLabel.Caption:=lisLFMFileContainsInvalidProperties;
511
540
ErrorsGroupBox.Caption:=lisErrors;
512
541
LFMGroupBox.Caption:=lisLFMFile;