mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 14:19:19 +02:00
197 lines
6.1 KiB
ObjectPascal
197 lines
6.1 KiB
ObjectPascal
unit FormFileConv;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Forms, Controls, contnrs,
|
|
// codetools
|
|
LFMTrees, CodeCache, LinkScanner, BasicCodeTools, KeywordFuncLists,
|
|
// Converter
|
|
ConverterTypes, ConvCodeTool;
|
|
|
|
type
|
|
|
|
{ TFormFileConverter }
|
|
|
|
TFormFileConverter = class
|
|
private
|
|
fCTLink: TCodeToolLink; // Link to codetools.
|
|
fLFMBuf: TCodeBuffer;
|
|
fLFMTree: TLFMTree;
|
|
fVisOffsets: TVisualOffsets;
|
|
fSrcCoordOffs: TObjectList;
|
|
fSrcNewProps: TObjectList;
|
|
// Statusbar has Panels. "SimplePanel = False" must be added if not there.
|
|
fSBHasPanels: Boolean;
|
|
fSBHasSimplePanelProp: Boolean;
|
|
fSBHasSimpleText: Boolean;
|
|
// Position for possible insertion of "SimplePanel = False".
|
|
fSBEndPos: integer;
|
|
function LeadingSpaceCount(Pos: integer): integer;
|
|
procedure AddStatusbarProp(ParentType: string);
|
|
procedure DoProperty(AProperty: TLFMPropertyNode; const GrandParType, AParentType: string);
|
|
function DoObjectValues(ObjectNode: TLFMObjectNode; const GrandParType: string): boolean;
|
|
public
|
|
constructor Create(ACTLink: TCodeToolLink; ALFMBuf: TCodeBuffer);
|
|
destructor Destroy; override;
|
|
function Convert: TModalResult;
|
|
public
|
|
property VisOffsets: TVisualOffsets read fVisOffsets write fVisOffsets;
|
|
property SrcCoordOffs: TObjectList read fSrcCoordOffs write fSrcCoordOffs;
|
|
property SrcNewProps: TObjectList read fSrcNewProps write fSrcNewProps;
|
|
end;
|
|
|
|
|
|
implementation
|
|
|
|
|
|
{ TFormFileConverter }
|
|
|
|
constructor TFormFileConverter.Create(ACTLink: TCodeToolLink; ALFMBuf: TCodeBuffer);
|
|
begin
|
|
inherited Create;
|
|
fCTLink:=ACTLink;
|
|
fLFMBuf:=ALFMBuf;
|
|
end;
|
|
|
|
destructor TFormFileConverter.Destroy;
|
|
begin
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TFormFileConverter.LeadingSpaceCount(Pos: integer): integer;
|
|
// returns the number of spaces in front of Pos in fLFMBuf.Source.
|
|
begin
|
|
Result:=0;
|
|
while (Pos>=0) and not (fLFMBuf.Source[Pos] in [#10,#13]) do begin
|
|
if fLFMBuf.Source[Pos] = ' ' then
|
|
Inc(Result);
|
|
Dec(Pos);
|
|
end;
|
|
end;
|
|
|
|
procedure TFormFileConverter.AddStatusbarProp(ParentType: string);
|
|
// Add 'SimplePanel = False' property if it is needed.
|
|
var
|
|
SpaceCnt, StartPos: integer;
|
|
s: string;
|
|
begin
|
|
if fSBEndPos<>-1 then begin
|
|
if fSBHasPanels and (not fSBHasSimpleText) and (not fSBHasSimplePanelProp) then begin
|
|
SpaceCnt:=LeadingSpaceCount(fSBEndPos);
|
|
// 2 spaces for indentation, then spaces in front of 'end'.
|
|
s:=StringOfChar(' ', SpaceCnt+2);
|
|
StartPos:=FindLineEndOrCodeInFrontOfPosition(fLFMBuf.Source,fSBEndPos,1,false);
|
|
fSrcNewProps.Add(TAddPropEntry.Create(StartPos, StartPos, LineEnding+s,
|
|
'SimplePanel = False', ParentType));
|
|
end;
|
|
fSBHasPanels:=False;
|
|
fSBHasSimplePanelProp:=False;
|
|
fSBEndPos:=-1; // Ready for next round.
|
|
end;
|
|
end;
|
|
|
|
procedure TFormFileConverter.DoProperty(AProperty: TLFMPropertyNode;
|
|
const GrandParType, AParentType: string);
|
|
// Take care of certain properties like Top and Left to be adjusted later.
|
|
// Parameters: AProperty is the property node
|
|
// GrandParType and AParentType are the class type names.
|
|
var
|
|
ind: Integer;
|
|
ValNode: TLFMValueNode;
|
|
CurNode: TLFMTreeNode;
|
|
Prop: string;
|
|
begin
|
|
// complete property name
|
|
Prop:=AProperty.CompleteName;
|
|
if Prop='' then exit;
|
|
if AParentType='TStatusBar' then begin
|
|
if Prop='SimplePanel' then begin
|
|
if AProperty.FirstChild.TheType=lfmnValue then
|
|
fSBHasSimplePanelProp:=True;
|
|
end
|
|
else if Prop='SimpleText' then begin
|
|
if AProperty.FirstChild.TheType=lfmnValue then
|
|
fSBHasSimpleText:=True;
|
|
end
|
|
else if Prop='Panels' then begin
|
|
CurNode:=AProperty.FirstChild;
|
|
while CurNode<>nil do begin
|
|
// Collection items have ValueType=lfmvList, there are items under Panels.
|
|
if (CurNode.TheType=lfmnValue) and (TLFMValueNode(CurNode).ValueType=lfmvCollection) then
|
|
fSBHasPanels:=True;
|
|
CurNode:=CurNode.NextSibling;
|
|
end;
|
|
end;
|
|
fSBEndPos:=AProperty.EndPos;
|
|
end;
|
|
if (Prop='Top') or (Prop='Left') then begin
|
|
if (GrandParType<>'') and fVisOffsets.Find(GrandParType, ind) then begin
|
|
if AProperty.FirstChild is TLFMValueNode then begin
|
|
Assert(AProperty.FirstChild.TheType=lfmnValue,
|
|
'Property.FirstChild.TheType should be lfmnValue');
|
|
ValNode:=AProperty.FirstChild as TLFMValueNode;
|
|
fSrcCoordOffs.Add(TSrcPropOffset.Create(GrandParType,AParentType,
|
|
Prop,ValNode.StartPos));
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TFormFileConverter.DoObjectValues(ObjectNode: TLFMObjectNode;
|
|
const GrandParType: string): boolean;
|
|
var
|
|
CurNode: TLFMTreeNode;
|
|
ParentType: string;
|
|
begin
|
|
fSBHasPanels:=False;
|
|
fSBHasSimplePanelProp:=False;
|
|
fSBEndPos:=-1;
|
|
ParentType:=ObjectNode.TypeName;
|
|
CurNode:=ObjectNode.FirstChild;
|
|
while CurNode<>nil do begin
|
|
case CurNode.TheType of
|
|
lfmnObject: begin
|
|
AddStatusbarProp(ParentType); // Check if previous object was a statusbar.
|
|
DoObjectValues(TLFMObjectNode(CurNode), ParentType); // Recursive call.
|
|
end;
|
|
lfmnProperty:
|
|
DoProperty(TLFMPropertyNode(CurNode), GrandParType, ParentType);
|
|
end;
|
|
CurNode:=CurNode.NextSibling;
|
|
end;
|
|
AddStatusbarProp(ParentType);
|
|
Result:=true;
|
|
end;
|
|
|
|
function TFormFileConverter.Convert: TModalResult;
|
|
var
|
|
CurRootNode: TLFMTreeNode;
|
|
RootObjNode: TLFMObjectNode;
|
|
begin
|
|
Result:=mrCancel;
|
|
// create tree from LFM file
|
|
fLFMTree:=DefaultLFMTrees.GetLFMTree(fLFMBuf,true);
|
|
fCTLink.CodeTool.ActivateGlobalWriteLock;
|
|
try
|
|
if not fLFMTree.ParseIfNeeded then exit;
|
|
fCTLink.CodeTool.BuildTree(lsrImplementationStart);
|
|
// Iterate the root objects
|
|
CurRootNode:=fLFMTree.Root;
|
|
while CurRootNode is TLFMObjectNode do begin
|
|
RootObjNode:=TLFMObjectNode(CurRootNode);
|
|
if RootObjNode.TypeName='' then exit;
|
|
if not DoObjectValues(RootObjNode, '') then exit;
|
|
CurRootNode:=CurRootNode.NextSibling;
|
|
end;
|
|
finally
|
|
fCTLink.CodeTool.DeactivateGlobalWriteLock;
|
|
end;
|
|
Result:=mrOK;
|
|
end;
|
|
|
|
end.
|
|
|