Ast editor custom draw

This commit is contained in:
Michael Schimmel
2025-12-06 17:32:04 +01:00
parent 9ed563bcc1
commit e40f56eaeb
10 changed files with 1629 additions and 1439 deletions
+233 -345
View File
@@ -9,20 +9,18 @@ uses
System.UITypes,
System.Generics.Collections,
FMX.Types,
FMX.Controls,
FMX.StdCtrls,
FMX.Graphics,
Myc.Data.Value,
Myc.Data.Keyword,
Myc.Ast,
Myc.Ast.Nodes,
Myc.Ast.Identities,
Myc.Fmx.AstEditor.Layout,
Myc.Fmx.AstEditor.Node;
Myc.Fmx.AstEditor.Render, // The new Virtual Engine
Myc.Fmx.AstEditor.Node; // The View Node
type
// --- Abstract List Base ---
// Now implements IReorderable to support drag & drop reordering
// Implements IReorderable to support drag & drop reordering within the virtual tree
TNodeListHandler<T: IAstNode> = class(TBaseNodeHandler<INodeList<T>>, IReorderable)
protected
FChildNodes: TList<TAstViewNode>;
@@ -35,7 +33,7 @@ type
function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; abstract;
// IReorderable Implementation
function CanDrag(Child: TControl): Boolean;
function CanDrag(Child: TVisualNode): Boolean;
procedure MoveChild(SourceIndex, TargetIndex: Integer);
end;
@@ -75,7 +73,7 @@ type
TRecordFieldHandler = class(TBaseNodeHandler<IRecordFieldNode>)
private
FKeyLabel: TLabel;
FKeyLabel: TTextNode;
FValueNode: TAstViewNode;
public
procedure BuildUI(OwnerNode: TAstViewNode); override;
@@ -322,47 +320,45 @@ begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := GetOrientation;
OwnerNode.Alignment := GetAlignment;
// No BeginUpdate/EndUpdate needed for TVisualNode, just property setting
OwnerNode.Frameless := True;
OwnerNode.Orientation := GetOrientation;
OwnerNode.Alignment := GetAlignment;
if openTok <> '' then
OwnerNode.AddLabel(OwnerNode, openTok);
if openTok <> '' then
OwnerNode.AddLabel(OwnerNode, openTok);
for i := 0 to FNode.Count - 1 do
for i := 0 to FNode.Count - 1 do
begin
childView := visu.CallAccept(FNode[i]);
FChildNodes.Add(childView);
if (i < FNode.Count - 1) and (sep <> '') and (sep <> ' ') then
OwnerNode.AddLabel(OwnerNode, sep);
end;
if closeTok <> '' then
OwnerNode.AddLabel(OwnerNode, closeTok);
if FNode.Count = 0 then
begin
if (openTok = '') and (closeTok = '') then
begin
childView := visu.CallAccept(FNode[i]);
FChildNodes.Add(childView);
if (i < FNode.Count - 1) and (sep <> '') and (sep <> ' ') then
OwnerNode.AddLabel(OwnerNode, sep);
var lbl := OwnerNode.AddLabel(OwnerNode, 'ø');
lbl.Opacity := 0.5;
end;
if closeTok <> '' then
OwnerNode.AddLabel(OwnerNode, closeTok);
if FNode.Count = 0 then
begin
if (openTok = '') and (closeTok = '') then
begin
var lbl := OwnerNode.AddLabel(OwnerNode, 'ø');
lbl.Opacity := 0.5;
end;
end;
finally
OwnerNode.EndUpdate;
end;
end;
// IReorderable Implementation
function TNodeListHandler<T>.CanDrag(Child: TControl): Boolean;
function TNodeListHandler<T>.CanDrag(Child: TVisualNode): Boolean;
begin
// Allow dragging only if the child is one of our managed ViewNodes
Result := (Child is TAstViewNode) and FChildNodes.Contains(TAstViewNode(Child));
// Only allow dragging if the child is one of our managed ViewNodes
if Child is TAstViewNode then
Result := FChildNodes.Contains(TAstViewNode(Child))
else
Result := False;
end;
procedure TNodeListHandler<T>.MoveChild(SourceIndex, TargetIndex: Integer);
@@ -385,8 +381,7 @@ begin
FChildNodes.Delete(SourceIndex);
FChildNodes.Insert(TargetIndex, item);
// The visual order update will happen upon the next ReconstructAst -> Compile -> BuildUI cycle
// triggered by the controller.
// The visual order update happens via the controller's compilation cycle
end;
{ TParameterListHandler }
@@ -482,26 +477,20 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
OwnerNode.Alignment := laCenter;
FKeyLabel := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Key.Value.Name);
FKeyLabel.Font.Style := FKeyLabel.Font.Style + [TFontStyle.fsBold];
FKeyLabel.StyledSettings := FKeyLabel.StyledSettings - [TStyledSetting.FontColor];
FKeyLabel.FontColor := TAlphaColors.Mediumvioletred;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
OwnerNode.Alignment := laCenter;
FValueNode := visu.CallAccept(FNode.Value);
finally
OwnerNode.EndUpdate;
end;
FKeyLabel := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Key.Value.Name);
FKeyLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FKeyLabel.Color := TAlphaColors.Mediumvioletred;
FValueNode := visu.CallAccept(FNode.Value);
end;
function TRecordFieldHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
begin
// Updated to use new Factory Overload to preserve Identity
Result := TAst.RecordField(FNode.Identity, FNode.Key, FValueNode.CreateAst);
end;
@@ -511,33 +500,25 @@ procedure TConstantNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
valueStr: string;
isConcise: Boolean;
titleLabel: TLabel;
valueLabel: TLabel;
titleLabel: TTextNode;
begin
OwnerNode.BeginUpdate;
try
valueStr := FNode.Value.ToString;
isConcise := ((FNode.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40);
valueStr := FNode.Value.ToString;
isConcise := ((FNode.Value.Kind = TDataValueKind.vkScalar) or (Pos(sLineBreak, valueStr) = 0)) and (Length(valueStr) < 40);
if isConcise then
begin
OwnerNode.Frameless := True;
OwnerNode.AddLabel(OwnerNode, valueStr);
end
else
begin
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
if isConcise then
begin
OwnerNode.Frameless := True;
OwnerNode.AddLabel(OwnerNode, valueStr);
end
else
begin
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Const');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Const');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
valueLabel := OwnerNode.AddLabel(OwnerNode, valueStr);
valueLabel.AutoSize := False;
valueLabel.WordWrap := True;
end;
finally
OwnerNode.EndUpdate;
OwnerNode.AddLabel(OwnerNode, valueStr);
end;
end;
@@ -550,13 +531,8 @@ end;
procedure TIdentifierNodeHandler.BuildUI(OwnerNode: TAstViewNode);
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.AddLabel(OwnerNode, FNode.Name);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.AddLabel(OwnerNode, FNode.Name);
end;
function TIdentifierNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -568,17 +544,11 @@ end;
procedure TKeywordNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
lbl: TLabel;
lbl: TTextNode;
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
lbl := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Value.Name);
lbl.StyledSettings := lbl.StyledSettings - [TStyledSetting.FontColor];
lbl.FontColor := TAlphaColors.Mediumvioletred;
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
lbl := OwnerNode.AddLabel(OwnerNode, ':' + FNode.Value.Name);
lbl.Color := TAlphaColors.Mediumvioletred;
end;
function TKeywordNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -590,19 +560,14 @@ end;
procedure TNopNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
lbl: TLabel;
lbl: TTextNode;
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Alignment := TLayoutAlignment.laCenter;
OwnerNode.Orientation := TLayoutOrientation.loHorizontal;
lbl := OwnerNode.AddLabel(OwnerNode, '...');
lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
lbl.Margins.Rect := TRectF.Create(8, 4, 8, 4);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.Alignment := TLayoutAlignment.laCenter;
OwnerNode.Orientation := TLayoutOrientation.loHorizontal;
lbl := OwnerNode.AddLabel(OwnerNode, '...');
lbl.FontSettings.Font.Style := [TFontStyle.fsBold];
lbl.Margins := TMarginRect.Create(8, 4, 8, 4);
end;
function TNopNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -615,23 +580,19 @@ end;
procedure TBlockExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'do');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
FExpressionsNode := visu.CallAccept(FNode.Expressions);
FExpressionsNode.Frameless := True;
finally
OwnerNode.EndUpdate;
end;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'do');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FExpressionsNode := visu.CallAccept(FNode.Expressions);
FExpressionsNode.Frameless := True;
end;
function TBlockExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -643,19 +604,14 @@ end;
procedure TIfExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
FConditionNode := OwnerNode.AddExpr(OwnerNode, 'if', FNode.Condition);
FThenNode := OwnerNode.AddExpr(OwnerNode, 'then', FNode.ThenBranch);
if Assigned(FNode.ElseBranch) then
FElseNode := OwnerNode.AddExpr(OwnerNode, 'else', FNode.ElseBranch);
finally
OwnerNode.EndUpdate;
end;
FConditionNode := OwnerNode.AddExpr(OwnerNode, 'if', FNode.Condition);
FThenNode := OwnerNode.AddExpr(OwnerNode, 'then', FNode.ThenBranch);
if Assigned(FNode.ElseBranch) then
FElseNode := OwnerNode.AddExpr(OwnerNode, 'else', FNode.ElseBranch);
end;
function TIfExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -677,18 +633,14 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FConditionNode := visu.CallAccept(FNode.Condition);
OwnerNode.AddLabel(OwnerNode, '?');
FThenNode := visu.CallAccept(FNode.ThenBranch);
OwnerNode.AddLabel(OwnerNode, ':');
FElseNode := visu.CallAccept(FNode.ElseBranch);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FConditionNode := visu.CallAccept(FNode.Condition);
OwnerNode.AddLabel(OwnerNode, '?');
FThenNode := visu.CallAccept(FNode.ThenBranch);
OwnerNode.AddLabel(OwnerNode, ':');
FElseNode := visu.CallAccept(FNode.ElseBranch);
end;
function TTernaryExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -701,31 +653,27 @@ end;
procedure TLambdaExpressionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleContainer: TAutoFitControl;
lbl: TLabel;
titleContainer: TAutoFitLayout;
lbl: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, 0);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
OwnerNode.BackgroundColor := $090000ff;
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
lbl := OwnerNode.AddLabel(titleContainer, 'fn');
lbl.Font.Style := lbl.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
OwnerNode.BackgroundColor := $090000ff;
// Parameters: Delegate to List Handler
var paramVisu := visu.Clone(titleContainer, 0);
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
lbl := OwnerNode.AddLabel(titleContainer, 'fn');
lbl.FontSettings.Font.Style := [TFontStyle.fsBold];
// Body
FBodyNode := visu.CallAccept(FNode.Body);
FBodyNode.Frameless := False;
finally
OwnerNode.EndUpdate;
end;
// Parameters: Delegate to List Handler
var paramVisu := visu.Clone(titleContainer, 0);
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
// Body
FBodyNode := visu.CallAccept(FNode.Body);
FBodyNode.Frameless := False;
end;
function TLambdaExpressionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -749,23 +697,19 @@ end;
procedure TFunctionCallNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
callLabel: TLabel;
callLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
callLabel := OwnerNode.AddLabel(OwnerNode, 'call ');
callLabel.Font.Style := callLabel.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FCalleeNode := visu.CallAccept(FNode.Callee);
callLabel := OwnerNode.AddLabel(OwnerNode, 'call ');
callLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FArgumentsNode := visu.CallAccept(FNode.Arguments);
finally
OwnerNode.EndUpdate;
end;
FCalleeNode := visu.CallAccept(FNode.Callee);
FArgumentsNode := visu.CallAccept(FNode.Arguments);
end;
function TFunctionCallNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -787,19 +731,15 @@ end;
procedure TMacroExpansionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Expansion');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Macro Expansion');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FExpandedBodyNode := visu.CallAccept(FNode.ExpandedBody);
end;
function TMacroExpansionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -812,21 +752,17 @@ end;
procedure TRecurNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FArgumentsNode := visu.CallAccept(FNode.Arguments);
finally
OwnerNode.EndUpdate;
end;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'recur');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FArgumentsNode := visu.CallAccept(FNode.Arguments);
end;
function TRecurNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -839,29 +775,25 @@ end;
procedure TVariableDeclarationNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
varLabel: TLabel;
varLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
varLabel := OwnerNode.AddLabel(OwnerNode, 'var');
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
varLabel.Font.Style := varLabel.Font.Style + [TFontStyle.fsBold];
FTargetNode := visu.CallAccept(FNode.Target);
varLabel := OwnerNode.AddLabel(OwnerNode, 'var');
if Assigned(FNode.Initializer) then
begin
OwnerNode.AddLabel(OwnerNode, ':=');
FInitializerNode := visu.CallAccept(FNode.Initializer);
end
else
FInitializerNode := nil;
finally
OwnerNode.EndUpdate;
end;
varLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FTargetNode := visu.CallAccept(FNode.Target);
if Assigned(FNode.Initializer) then
begin
OwnerNode.AddLabel(OwnerNode, ':=');
FInitializerNode := visu.CallAccept(FNode.Initializer);
end
else
FInitializerNode := nil;
end;
function TVariableDeclarationNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -882,16 +814,12 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FTargetNode := visu.CallAccept(FNode.Target);
OwnerNode.AddLabel(OwnerNode, ':=');
FValueNode := visu.CallAccept(FNode.Value);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FTargetNode := visu.CallAccept(FNode.Target);
OwnerNode.AddLabel(OwnerNode, ':=');
FValueNode := visu.CallAccept(FNode.Value);
end;
function TAssignmentNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -904,27 +832,23 @@ end;
procedure TMacroDefinitionNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleContainer: TAutoFitControl;
titleLabel: TTextNode;
titleContainer: TAutoFitLayout;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
titleLabel := OwnerNode.AddLabel(titleContainer, 'Macro Def: ' + FNode.Name.Name);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
// Parameters List
var paramVisu := visu.Clone(titleContainer, visu.ExprDepth);
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
titleContainer := OwnerNode.AddContainer(OwnerNode, loHorizontal, laCenter);
titleLabel := OwnerNode.AddLabel(titleContainer, 'Macro Def: ' + FNode.Name.Name);
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FBodyNode := visu.CallAccept(FNode.Body);
finally
OwnerNode.EndUpdate;
end;
// Parameters List
var paramVisu := visu.Clone(titleContainer, visu.ExprDepth);
FParamsNode := paramVisu.CallAccept(FNode.Parameters);
FBodyNode := visu.CallAccept(FNode.Body);
end;
function TMacroDefinitionNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -937,19 +861,15 @@ end;
procedure TQuasiquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Quasiquote');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
end;
function TQuasiquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -962,26 +882,25 @@ end;
procedure TUnquoteNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
leftBracket, rightBracket: TLabel;
leftBracket, rightBracket: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
leftBracket := OwnerNode.AddLabel(OwnerNode, '<');
leftBracket.Padding.Right := 0;
leftBracket.Margins.Right := 0;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FExpressionNode := visu.CallAccept(FNode.Expression);
leftBracket := OwnerNode.AddLabel(OwnerNode, '<');
// We cannot assign to fields of record properties directly.
// Replace the entire margin record.
// Default from AddLabel is (cNodePadding, cTitleTopPadding, cNodePadding, cTitleBottomPadding)
// We want Right Margin = 0.
leftBracket.Margins := TMarginRect.Create(cNodePadding, cTitleTopPadding, 0, cTitleBottomPadding);
rightBracket := OwnerNode.AddLabel(OwnerNode, '>');
rightBracket.Padding.Left := 0;
rightBracket.Margins.Left := 0;
finally
OwnerNode.EndUpdate;
end;
FExpressionNode := visu.CallAccept(FNode.Expression);
rightBracket := OwnerNode.AddLabel(OwnerNode, '>');
// We want Left Margin = 0.
rightBracket.Margins := TMarginRect.Create(0, cTitleTopPadding, cNodePadding, cTitleBottomPadding);
end;
function TUnquoteNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -994,19 +913,15 @@ end;
procedure TUnquoteSplicingNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Unquote-Splicing');
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FExpressionNode := visu.CallAccept(FNode.Expression);
end;
function TUnquoteSplicingNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -1021,17 +936,13 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
OwnerNode.AddLabel(OwnerNode, '[');
FIndexNode := visu.CallAccept(FNode.Index);
OwnerNode.AddLabel(OwnerNode, ']');
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
OwnerNode.AddLabel(OwnerNode, '[');
FIndexNode := visu.CallAccept(FNode.Index);
OwnerNode.AddLabel(OwnerNode, ']');
end;
function TIndexerNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -1046,21 +957,16 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
OwnerNode.AddLabel(OwnerNode, '.');
OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := True;
OwnerNode.Orientation := loHorizontal;
FBaseNode := visu.CallAccept(FNode.Base);
OwnerNode.AddLabel(OwnerNode, '.');
OwnerNode.AddLabel(OwnerNode, FNode.Member.Value.Name);
end;
function TMemberAccessNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
begin
// Reuse Identifier, Reuse Member Keyword (via TAst.Keyword with Identity)
Result := TAst.MemberAccess(FNode.Identity, FBaseNode.CreateAst, TAst.Keyword(FNode.Member.Identity.AsKeyword), FNode.StaticType);
end;
@@ -1071,17 +977,13 @@ var
visu: IAstVisualizer;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
// Delegate to RecordFieldList
FFieldsNode := visu.CallAccept(FNode.Fields);
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
OwnerNode.Alignment := laFlush;
// Delegate to RecordFieldList
FFieldsNode := visu.CallAccept(FNode.Fields);
end;
function TRecordLiteralNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -1100,17 +1002,12 @@ end;
procedure TCreateSeriesNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
titleLabel: TLabel;
titleLabel: TTextNode;
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Create Series: ' + FNode.Definition);
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
end;
function TCreateSeriesNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -1123,25 +1020,21 @@ end;
procedure TAddSeriesItemNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
visu: IAstVisualizer;
titleLabel: TLabel;
titleLabel: TTextNode;
begin
visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1);
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
FValueNode := visu.CallAccept(FNode.Value);
if Assigned(FNode.Lookback) then
FLookbackNode := visu.CallAccept(FNode.Lookback)
else
FLookbackNode := nil;
finally
OwnerNode.EndUpdate;
end;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Add Item to: ' + FNode.Series.Name);
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
FValueNode := visu.CallAccept(FNode.Value);
if Assigned(FNode.Lookback) then
FLookbackNode := visu.CallAccept(FNode.Lookback)
else
FLookbackNode := nil;
end;
function TAddSeriesItemNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;
@@ -1167,17 +1060,12 @@ end;
procedure TSeriesLengthNodeHandler.BuildUI(OwnerNode: TAstViewNode);
var
titleLabel: TLabel;
titleLabel: TTextNode;
begin
OwnerNode.BeginUpdate;
try
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name);
titleLabel.Font.Style := titleLabel.Font.Style + [TFontStyle.fsBold];
finally
OwnerNode.EndUpdate;
end;
OwnerNode.Frameless := False;
OwnerNode.Orientation := loVertical;
titleLabel := OwnerNode.AddLabel(OwnerNode, 'Length of: ' + FNode.Series.Name);
titleLabel.FontSettings.Font.Style := [TFontStyle.fsBold];
end;
function TSeriesLengthNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode;