unit Myc.Fmx.AstEditor.Handlers.Pipes; interface uses System.SysUtils, System.UITypes, System.Types, Myc.Ast, Myc.Ast.Nodes, Myc.Fmx.AstEditor.Render, Myc.Fmx.AstEditor.Node, Myc.Fmx.AstEditor.Handlers; type // --- Pipe Container --- TPipeNodeHandler = class(TBaseNodeHandler) private FInputsNode: TAstViewNode; FTransformNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Pipe Inputs --- TPipeInputListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; function GetAlignment: TLayoutAlignment; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; TPipeInputNodeHandler = class(TBaseNodeHandler) private FStreamNode: TAstViewNode; FSelectorsNode: TAstViewNode; public procedure BuildUI(OwnerNode: TAstViewNode); override; function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; // --- Selectors --- TPipeSelectorListHandler = class(TNodeListHandler) protected function GetOrientation: TLayoutOrientation; override; public function ReconstructAst(OwnerNode: TAstViewNode): IAstNode; override; end; implementation { TPipeNodeHandler } procedure TPipeNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; header: TTextNode; arrow: TTextNode; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth + 1); OwnerNode.Frameless := False; OwnerNode.Orientation := loVertical; OwnerNode.Alignment := laCenter; // Distinct background color for Pipes to make them stand out as data flows OwnerNode.BackgroundColor := $FF202530; OwnerNode.BorderColor := TAlphaColors.Slateblue; // Header header := OwnerNode.AddLabel(OwnerNode, 'Pipe Pipeline'); header.FontSettings.Font.Style := [TFontStyle.fsBold]; header.Color := TAlphaColors.Lightskyblue; // Section 1: Inputs FInputsNode := visu.CallAccept(FNode.Inputs); // Visual Separator / Direction indicator arrow := OwnerNode.AddLabel(OwnerNode, '▼ Transform ▼'); arrow.FontSettings.Font.Size := 10; arrow.Color := TAlphaColors.Gray; arrow.Margins := TMarginRect.Create(0, 5, 0, 5); // Section 2: Transformation (Lambda) FTransformNode := visu.CallAccept(FNode.Transformation); end; function TPipeNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.Pipe(FNode.Identity, FInputsNode.CreateAst.AsPipeInputList, FTransformNode.CreateAst.AsLambdaExpression, FNode.StaticType); end; { TPipeInputListHandler } function TPipeInputListHandler.GetOrientation: TLayoutOrientation; begin // Stack inputs vertically Result := loVertical; end; function TPipeInputListHandler.GetAlignment: TLayoutAlignment; begin Result := laFlush; end; function TPipeInputListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst.AsPipeInput; Result := TPipeInputList.Create(arr, FNode.Identity); end; { TPipeInputNodeHandler } procedure TPipeInputNodeHandler.BuildUI(OwnerNode: TAstViewNode); var visu: IAstVisualizer; begin visu := OwnerNode.Visualizer.Clone(OwnerNode, OwnerNode.Visualizer.ExprDepth); OwnerNode.Frameless := True; OwnerNode.Orientation := loHorizontal; OwnerNode.Alignment := laCenter; // "StreamName [ :Col :Col ]" FStreamNode := visu.CallAccept(FNode.StreamSource); // Add small spacing var spacer := TAutoFitLayout.Create(OwnerNode.Host); spacer.Size := TSizeF.Create(5, 5); OwnerNode.AddChild(spacer); FSelectorsNode := visu.CallAccept(FNode.Selectors); end; function TPipeInputNodeHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; begin Result := TAst.PipeInput( FNode.StreamSource, // Identifiers are immutable usually, or re-create if needed FSelectorsNode.CreateAst.AsPipeSelectorList, FNode.Identity.Location ); end; { TPipeSelectorListHandler } function TPipeSelectorListHandler.GetOrientation: TLayoutOrientation; begin // Selectors are horizontal: [:A :B :C] Result := loHorizontal; end; function TPipeSelectorListHandler.ReconstructAst(OwnerNode: TAstViewNode): IAstNode; var arr: TArray; i: Integer; begin SetLength(arr, FChildNodes.Count); for i := 0 to FChildNodes.Count - 1 do arr[i] := FChildNodes[i].CreateAst.AsKeyword; Result := TPipeSelectorList.Create(arr, FNode.Identity); end; end.