diff --git a/ASTPlayground/Myc.Ast.Visualizer.pas b/ASTPlayground/Myc.Ast.Visualizer.pas index 82a1bc0..0d71c91 100644 --- a/ASTPlayground/Myc.Ast.Visualizer.pas +++ b/ASTPlayground/Myc.Ast.Visualizer.pas @@ -131,10 +131,12 @@ type procedure MouseMove(Shift: TShiftState; X, Y: Single); override; procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single); override; procedure MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); override; + procedure DblClick; override; public constructor Create(AOwner: TComponent); override; procedure BuildTree(const Root: IAstNode; const Position: TPointF; AMode: TVisualizationMode); function GetChildrenMatrix(var Matrix: TMatrix; var Simple: Boolean): Boolean; override; + function Zoom(Factor: Single): Boolean; published // Standard control properties @@ -752,37 +754,15 @@ begin end; procedure TAuraWorkspace.MouseWheel(Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean); -var - oldZoom: Single; - MouseService: IFMXMouseService; begin inherited; + Handled := Zoom(IfThen(WheelDelta > 0, FZoom * 1.1, FZoom / 1.1)); +end; - if TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, MouseService) then - begin - var MousePos := ScreenToLocal(MouseService.GetMousePos); - - oldZoom := FZoom; - - // Calculate new zoom - if WheelDelta > 0 then - FZoom := FZoom * 1.1 - else - FZoom := FZoom / 1.1; - - // Clamp zoom level to a reasonable range - FZoom := Max(0.2, Min(3.0, FZoom)); - - // Adjust panning to keep the point under the cursor stationary - FPanning.cx := MousePos.X * (1 - FZoom / oldZoom) + FPanning.cx * (FZoom / oldZoom); - FPanning.cy := MousePos.Y * (1 - FZoom / oldZoom) + FPanning.cy * (FZoom / oldZoom); - - // Trigger repaint to apply the new transformation matrix - RecalcAbsolute; - RecalcUpdateRect; - Repaint; - Handled := True; - end; +procedure TAuraWorkspace.DblClick; +begin + inherited; + Zoom(1.0); end; procedure TAuraWorkspace.Paint; @@ -836,6 +816,31 @@ begin end; end; +function TAuraWorkspace.Zoom(Factor: Single): Boolean; +var + MouseService: IFMXMouseService; +begin + Result := TPlatformServices.Current.SupportsPlatformService(IFMXMouseService, MouseService); + if Result then + begin + var MousePos := ScreenToLocal(MouseService.GetMousePos); + + // Clamp zoom level to a reasonable range + Factor := Max(0.2, Min(3.0, Factor)); + + // Adjust panning to keep the point under the cursor stationary + FPanning.cx := MousePos.X * (1 - Factor / FZoom) + FPanning.cx * (Factor / FZoom); + FPanning.cy := MousePos.Y * (1 - Factor / FZoom) + FPanning.cy * (Factor / FZoom); + + FZoom := Factor; + + // Trigger repaint to apply the new transformation matrix + RecalcAbsolute; + RecalcUpdateRect; + Repaint; + end; +end; + { TAstToAuraNodeVisitor } constructor TAstToAuraNodeVisitor.Create( diff --git a/Doc/Roadmap.md b/Doc/Roadmap.md new file mode 100644 index 0000000..b148b27 --- /dev/null +++ b/Doc/Roadmap.md @@ -0,0 +1,80 @@ +### **Projektplan: Visueller AST-Editor für Handelsstrategien** + +* **Datum:** 08.09.2025 11:38 + +#### **Motivation** + +Ziel ist die Schaffung eines Systems, das es Fachexperten ohne Programmierkenntnisse ermöglicht, komplexe Handelsstrategien visuell zu entwerfen, zu debuggen und zu backtesten. Die traditionelle Hürde der textbasierten Programmierung wird durch einen rein visuellen, geführten Ansatz eliminiert, der Fehler von vornherein vermeidet. Eine Kernanforderung ist die robuste Schnittstelle für den Import und Export von Logik aus externen Quellen, insbesondere LLMs. + +#### **Ziel** + +Die Entwicklung einer dualen Systemarchitektur, die eine intuitive, fehlerresistente Entwicklungsumgebung von einer hochperformanten Backtesting-Engine trennt. Die Architektur muss eine strikte Trennung zwischen dem logischen Modell (AST) und dem visuellen Zustand (UI-Metadaten) gewährleisten, um eine hohe Datenintegrität bei internen und externen Bearbeitungen sicherzustellen und eine nahtlose Persistenz von Projekten zu ermöglichen. + +#### **Ergebnis: Architekturentwurf** + +Der Editor basiert auf einer verfeinerten Model-View-ViewModel-Architektur, die maximale Robustheit und Flexibilität gewährleistet. + +1. **Das Model: Der High-Level AST (HAST)** + * Der IAstNode-Baum ist die alleinige "Source of Truth" und enthält ausschließlich die reine, zustandslose Programmlogik. Diese Datenreinheit ist die Voraussetzung für die einfache Serialisierung und die Interaktion mit externen Systemen. +2. **Der Vermittler: Die ViewModel-Schicht** + * Ein parallel zum HAST existierender Baum aus TVisualNodeViewModel-Objekten dient als Brücke zur UI. + * Jedes ViewModel erhält eine **stabile, permanente ID** (TViewModelID), die es unabhängig von seiner Position im Baum macht. Diese ID ist der Schlüssel zur Lösung für stabile Bearbeitungen und Metadaten. +3. **Die Ansicht: Deterministisches Layout mit Overrides** + * Die visuelle Darstellung (TAuraNode-Controls) wird durch einen deterministischen Algorithmus aus dem ViewModel-Baum generiert (View \= f(ViewModel)). + * Manuelle Layout-Änderungen durch den Benutzer werden als "Overrides" in einer separaten Metadaten-Struktur gespeichert und über die stabile TViewModelID zugeordnet. +4. **Zweifaches Metadaten-System** + * **Logische Metadaten** (z.B. Farbkodierung) werden an den IAstNode gekoppelt und gelten für alle seine visuellen Instanzen. + * **Visuelle Instanz-Metadaten** (z.B. Position, IsCollapsed) werden an die stabile TViewModelID gekoppelt und gelten nur für eine spezifische Instanz. +5. **Duale Ausführungs-Engines & Serialisierung** + * Ein **HAST-Interpreter** arbeitet im Debug-Modus direkt auf dem HAST für eine reichhaltige UI-Erfahrung. + * Ein **CAST-Evaluator** arbeitet im Backtest-Modus auf einer optimierten Repräsentation (Core AST) für maximale Performance. + * Ein **duales Clipboard/Dateiformat** serialisiert entweder nur den reinen HAST (für LLMs) oder den HAST inklusive aller Metadaten (für Projekte). + +--- + +### **TODO: Priorisierte Roadmap** + +#### **Phase 1: Minimales Architektur-Fundament** + +* **Ziel:** Die technische Basis für alle weiteren Schritte schaffen. Dieser Schritt ist die Voraussetzung für die Serialisierung. +* **Schritte:** + 1. **ViewModel-Schicht implementieren:** Die TVisualNodeViewModel-Klasse mit der stabilen TViewModelID erstellen. + 2. **Metadaten-Strukturen aufbauen:** Die beiden Dictionaries für TLogicalMetadata (gekoppelt an IAstNode) und TVisualInstanceMetadata (gekoppelt an TViewModelID) definieren und implementieren. + 3. **Visitor refaktorisieren:** Den TAstToAuraNodeVisitor so umbauen, dass er den ViewModel-Baum erzeugt und dabei die stabilen IDs vergibt. + 4. **Layout-Engine implementieren:** Den deterministischen Layout-Algorithmus umsetzen, der die Basis-Positionierung vornimmt. Die Engine muss bereits in der Lage sein, Positions-Overrides aus den TVisualInstanceMetadata zu berücksichtigen. + +#### **Phase 2: Kern-Feature – Persistenz & Interoperabilität** + +* **Ziel:** Das System schnellstmöglich nutzbar machen, indem Projekte gespeichert/geladen und Logik extern ausgetauscht werden kann. +* **Schritte:** + 1. **Duale JSON-Serialisierung entwickeln:** + * **Routine A (Projekt):** Serialisiert den HAST und beide Metadaten-Systeme. + * **Routine B (Logik-Clipboard):** Serialisiert ausschließlich den reinen HAST. + 2. **Deserialisierung implementieren:** + * **"Projekt laden":** Stellt den HAST, den ViewModel-Baum und alle Metadaten aus der Projektdatei vollständig wieder her. + * **"Logik einfügen":** Eine pragmatische erste Version, die einen reinen HAST-Teilbaum deserialisiert, dafür neue ViewModels mit neuen IDs erzeugt und ihn von der Layout-Engine automatisch positionieren lässt. + 3. **UI-Anbindung:** Die Aktionen "Projekt speichern", "Projekt laden", "Logik als JSON kopieren" und "Logik aus JSON einfügen" in der UI implementieren. + +#### **Phase 3: Interaktivität & Benutzerführung** + +* **Ziel:** Den Editor um die volle, geführte Bearbeitungsfunktionalität erweitern. +* **Schritte:** + 1. **Command Pattern umsetzen:** IEditorCommand-Schnittstelle und TCommandManager für Undo/Redo erstellen. + 2. **Socket-basierte Controller-Logik entwickeln:** Die Interaktion implementieren, bei der Klicks auf Input-Sockets kontextsensitive Menüs mit validen Optionen öffnen. Jede Aktion wird über das Command-System abgewickelt. + 3. **Refactoring-Funktionen implementieren:** Visuelle Operationen wie "Zu Funktion zusammenfassen" umsetzen. + +#### **Phase 4: Ausführung & Debugging** + +* **Ziel:** Den im Editor erstellten HAST interaktiv ausführbar und debuggbar machen. +* **Schritte:** + 1. Den **HAST-Interpreter** (Debugger) implementieren oder ausbauen. + 2. Den Interpreter tief mit der UI und dem ViewModel-Baum koppeln, um Debugging-Features zu realisieren (visuelles Hervorheben, Breakpoints, Step-Logik etc.). + +#### **Phase 5: Performance & Optimierung** + +* **Ziel:** Die Ausführung von Strategien für die Massen-Datenverarbeitung optimieren und die UX verfeinern. +* **Schritte:** + 1. Die **CAST-Struktur** (Core AST) definieren. + 2. Den **HAST-zu-CAST-Expander** (Compiler/Visitor) entwickeln. + 3. Den "headless" **CAST-Evaluator** (Backtester) implementieren. + 4. Den **"Smart Paste"-Algorithmus** (Diff & Merge) als finale Verfeinerung für das Einfügen von Logik nachrüsten. \ No newline at end of file diff --git a/Doc/Transformation des AST-Visualisierers zum Interaktiven Editor.md b/Doc/Transformation des AST-Visualisierers zum Interaktiven Editor.md new file mode 100644 index 0000000..1167d58 --- /dev/null +++ b/Doc/Transformation des AST-Visualisierers zum Interaktiven Editor.md @@ -0,0 +1,46 @@ +### **Projektplan: Transformation des AST-Visualisierers zum Interaktiven Editor** + +* **Datum:** 08.09.2025 11:20 +* **Motivation** + * Der aktuelle AST-Visualisierer ist ein leistungsfähiges Anzeigetool. Um ihn zu einem interaktiven Werkzeug für die Skript-Entwicklung, \-Analyse und \-Modifikation weiterzuentwickeln, muss eine robuste Architektur für Zustandsverwaltung, Bearbeitung und Persistenz geschaffen werden. +* **Ziel** + * Die Entwicklung einer flexiblen Editor-Architektur, die eine klare Trennung zwischen dem logischen AST-Modell und seiner visuellen Repräsentation gewährleistet. Das System muss komplexe Anforderungen erfüllen: Es soll optionale Darstellungsmodi (Baum- vs. Graphen-Ansicht), zwei Arten von Metadaten (logisch vs. instanzspezifisch) und eine hohe Datenintegrität bei internen (z.B. Umsortieren) und externen (z.B. Einfügen von LLM-Code) Bearbeitungen sicherstellen. +* **Ergebnis** + * Ein interaktiver, visueller AST-Editor mit einem hochentwickelten Zustandsmanagement. Die Architektur bietet eine nahtlose Benutzererfahrung, bei der Layout-Anpassungen und Zustände (z.B. eingeklappte Knoten) auch bei komplexen Operationen wie Refactoring oder dem Mergen von extern modifiziertem Code intelligent erhalten bleiben. Das System ist durch ein flexibles JSON-Format persistent und interoperabel. + +--- + +### **TODO: Nächste Schritte** + +1. **Fundament: ViewModel-Schicht und Stabile IDs einführen** + * **Beschreibung:** Das Kernstück der neuen Architektur schaffen. Eine TVisualNodeViewModel-Klasse wird als Vermittler zwischen dem IAstNode-Modell und der TAuraNode-Ansicht eingeführt. + * **Umsetzung:** + * Jede TVisualNodeViewModel-Instanz erhält beim Erstellen eine einzigartige, permanente und strukturunabhängige TViewModelID (z.B. Int64). + * Der TAstToAuraNodeVisitor wird so umgebaut, dass er primär einen Baum aus ViewModel-Objekten erzeugt, welcher die Hierarchie des AST widerspiegelt. +2. **Zustandsverwaltung: Metadaten-System implementieren** + * **Beschreibung:** Die getrennte Speicherung von logischen und instanzspezifischen Metadaten implementieren. + * **Umsetzung:** + * **Logische Metadaten:** Eine zentrale TDictionary\ für Eigenschaften erstellen, die für alle Instanzen eines Knotens gelten (z.B. Farbkodierung). + * **Instanz-Metadaten:** Eine TDictionary\ für Eigenschaften erstellen, die nur für eine bestimmte visuelle Instanz gelten (z.B. IsCollapsed, Position auf der Leinwand). + * Die Rendering-Logik anpassen, um beide Metadatentypen beim Zeichnen eines TAuraNode zu berücksichtigen. +3. **Persistenz: JSON-Serialisierung erweitern** + * **Beschreibung:** Das Speichern und Laden des gesamten Editor-Zustands ermöglichen. + * **Umsetzung:** + * Einen Serialisierungsprozess entwerfen, der drei getrennte Bereiche in der JSON-Datei ablegt: + 1. Den reinen IAstNode-Baum. + 2. Die logischen Metadaten, verknüpft über eine temporäre ID des IAstNode. + 3. Die instanzspezifischen Metadaten, verknüpft über die stabile TViewModelID. +4. **Interaktion: Grundlegende Editierbarkeit herstellen** + * **Beschreibung:** Dem Benutzer erlauben, den AST-Graphen zu verändern (Knoten hinzufügen, löschen, umsortieren). + * **Umsetzung:** + * Das **Command Pattern** implementieren, bei dem jede Änderung eine Execute- und Unexecute-Methode hat (für Undo/Redo). + * Jeder Command ist dafür verantwortlich, sowohl das IAstNode-Modell als auch den TVisualNodeViewModel-Baum konsistent zu halten. Da die Metadaten an die stabilen IDs gekoppelt sind, bleiben sie bei diesen Operationen automatisch erhalten. +5. **Fortgeschrittene Interaktion: "Smart Paste" / Abgleich-Algorithmus** + * **Beschreibung:** Das intelligente Einfügen von extern veränderten AST-Teilbäumen ermöglichen. + * **Umsetzung:** + * Einen "Diff & Merge"-Algorithmus entwickeln. Beim Einfügen vergleicht dieser den neuen AST-Teilbaum mit dem alten. + * Bei äquivalenten Knoten werden die bestehenden TVisualNodeViewModel-Instanzen (samt ihrer IDs und Metadaten) wiederverwendet, um den visuellen Zustand zu erhalten. Nur bei echten Änderungen oder neuen Knoten werden neue ViewModels mit neuen IDs erzeugt. +6. **Optionale Ansicht: Eindeutige Knoten-Visualisierung ("Graph"-Modus)** + * **Beschreibung:** Den optionalen Modus implementieren, in dem jeder IAstNode nur einmal dargestellt wird. + * **Umsetzung:** + * Den TAstToAuraNodeVisitor um einen Modus erweitern. In diesem Modus führt er eine TDictionary\, um bereits erstellte ViewModels für einen IAstNode zu finden und wiederzuverwenden, anstatt neue zu erstellen. Stattdessen wird nur eine neue Verbindungslinie gezeichnet. \ No newline at end of file