diff --git a/Blockly/Delphi/MainUnit.fmx b/Blockly/Delphi/MainUnit.fmx
index 81ddf10..bc7a112 100644
--- a/Blockly/Delphi/MainUnit.fmx
+++ b/Blockly/Delphi/MainUnit.fmx
@@ -1,7 +1,7 @@
object MainForm: TMainForm
Left = 0
Top = 0
- Caption = 'Form1'
+ Caption = 'Blockly LLVM IR Generator'
ClientHeight = 872
ClientWidth = 1010
FormFactor.Width = 320
@@ -12,57 +12,66 @@ object MainForm: TMainForm
DesignerMasterStyle = 0
object WebBrowser1: TWebBrowser
Align = Top
- Anchors = [akLeft, akTop, akRight, akBottom]
+ Anchors = [akLeft, akTop]
Size.Width = 1010.000000000000000000
- Size.Height = 633.000000000000000000
+ Size.Height = 625.000000000000000000
Size.PlatformDefault = False
WindowsEngine = EdgeOnly
OnDidFinishLoad = WebBrowser1DidFinishLoad
- end
- object LauchSiteButton: TButton
- Anchors = [akLeft, akBottom]
- Position.X = 24.000000000000000000
- Position.Y = 744.000000000000000000
- TabOrder = 1
- Text = 'Lauch Site'
- TextSettings.Trimming = None
- OnClick = LauchSiteButtonClick
- end
- object SaveWorkspaceButton: TButton
- Anchors = [akLeft, akBottom]
- Position.X = 24.000000000000000000
- Position.Y = 774.000000000000000000
- Size.Width = 97.000000000000000000
- Size.Height = 22.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 2
- Text = 'Save Workspace'
- TextSettings.Trimming = None
- OnClick = SaveWorkspaceButtonClick
- end
- object GenerateCodeButton: TButton
- Anchors = [akLeft, akBottom]
- Position.X = 24.000000000000000000
- Position.Y = 804.000000000000000000
- Size.Width = 97.000000000000000000
- Size.Height = 22.000000000000000000
- Size.PlatformDefault = False
- TabOrder = 3
- Text = 'Generate Code'
- TextSettings.Trimming = None
- OnClick = GenerateCodeButtonClick
+ object ToolBar1: TToolBar
+ Size.Width = 1010.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 0
+ object RefreshButton: TSpeedButton
+ Align = Left
+ Size.Width = 80.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ Text = 'Refresh'
+ TextSettings.Trimming = None
+ OnClick = LauchSiteButtonClick
+ end
+ object SaveWorkspaceButton: TSpeedButton
+ Align = Left
+ Position.X = 80.000000000000000000
+ Size.Width = 80.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ Text = 'Save'
+ TextSettings.Trimming = None
+ OnClick = SaveWorkspaceButtonClick
+ end
+ object GenerateCodeButton: TSpeedButton
+ Align = Left
+ Position.X = 160.000000000000000000
+ Size.Width = 80.000000000000000000
+ Size.Height = 40.000000000000000000
+ Size.PlatformDefault = False
+ Text = 'Generate'
+ TextSettings.Trimming = None
+ OnClick = GenerateCodeButtonClick
+ end
+ end
end
object Memo: TMemo
Touch.InteractiveGestures = [Pan, LongTap, DoubleTap]
DataDetectorTypes = []
- Anchors = [akRight, akBottom]
- Position.X = 144.000000000000000000
- Position.Y = 641.000000000000000000
- Size.Width = 841.000000000000000000
- Size.Height = 223.000000000000000000
+ Align = Client
+ Size.Width = 1010.000000000000000000
+ Size.Height = 239.000000000000000000
+ Size.PlatformDefault = False
+ TabOrder = 1
+ Viewport.Width = 1006.000000000000000000
+ Viewport.Height = 235.000000000000000000
+ end
+ object Splitter1: TSplitter
+ Align = Top
+ Cursor = crVSplit
+ MinSize = 20.000000000000000000
+ Position.Y = 625.000000000000000000
+ Size.Width = 1010.000000000000000000
+ Size.Height = 8.000000000000000000
Size.PlatformDefault = False
- TabOrder = 4
- Viewport.Width = 837.000000000000000000
- Viewport.Height = 219.000000000000000000
end
end
diff --git a/Blockly/Delphi/MainUnit.pas b/Blockly/Delphi/MainUnit.pas
index 9717d48..73ff336 100644
--- a/Blockly/Delphi/MainUnit.pas
+++ b/Blockly/Delphi/MainUnit.pas
@@ -11,7 +11,7 @@ uses
const
// Pfad zur HTML-Datei
- PATH_BLOCKLY = 'T:\Myc\Blockly\blockly_LLVM.html';
+ PATH_BLOCKLY = 'T:\Myc\Blockly\index.html';
// Pfade zu den LLVM-Werkzeugen
CLANG_PATH = 'clang.exe';
@@ -20,10 +20,12 @@ const
type
TMainForm = class( TForm )
WebBrowser1: TWebBrowser;
- LauchSiteButton: TButton;
- SaveWorkspaceButton: TButton;
- GenerateCodeButton: TButton;
Memo: TMemo;
+ Splitter1: TSplitter;
+ ToolBar1: TToolBar;
+ RefreshButton: TSpeedButton;
+ SaveWorkspaceButton: TSpeedButton;
+ GenerateCodeButton: TSpeedButton;
procedure FormCreate( Sender: TObject );
procedure FormDestroy( Sender: TObject );
procedure LauchSiteButtonClick( Sender: TObject );
@@ -83,6 +85,7 @@ end;
procedure TMainForm.FormCreate( Sender: TObject );
begin
TLLVMRunner.Log := Memo.Lines;
+ LauchSiteButtonClick(Self);
end;
procedure TMainForm.FormDestroy( Sender: TObject );
@@ -104,7 +107,7 @@ var
cmdLine: string;
buffer: TBytes;
bytesRead: Cardinal;
- output, errors: string;
+ output: string;
begin
// Pipe für StdOut und StdErr erstellen
sa.nLength := SizeOf( TSecurityAttributes );
diff --git a/Blockly/blockly_llvm.html b/Blockly/blockly_llvm.html
deleted file mode 100644
index 854affb..0000000
--- a/Blockly/blockly_llvm.html
+++ /dev/null
@@ -1,192 +0,0 @@
-
-
-
-
- Blockly zu LLVM IR - Final
-
-
-
-
-LLVM IR (.dll) Generator
-Bauen Sie links Ihre Logik. Rechts erscheint der LLVM-Code, der zu einer 64-Bit DLL für Windows kompiliert werden kann.
-
-
-
-
-
-
-
-
-
-
-
Erzeugter LLVM-Code:
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Blockly/index.html b/Blockly/index.html
new file mode 100644
index 0000000..4e14cdd
--- /dev/null
+++ b/Blockly/index.html
@@ -0,0 +1,38 @@
+
+
+
+
+ Blockly zu LLVM IR - Final
+
+
+
+
+
+LLVM IR (.dll) Generator
+Bauen Sie links Ihre Logik. Rechts erscheint der LLVM-Code, der zu einer 64-Bit DLL für Windows kompiliert werden kann.
+
+
+
+
+
+
+
+
+
+
+
+
+
Erzeugter LLVM-Code:
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Blockly/script.js b/Blockly/script.js
new file mode 100644
index 0000000..a85c642
--- /dev/null
+++ b/Blockly/script.js
@@ -0,0 +1,429 @@
+window.onload = function() {
+
+ let workspace;
+ const isWebView = window.chrome && window.chrome.webview;
+
+ // === LLVM-IR-GENERATOR (FINALE VERSION) ===
+ Blockly.LLVM = new Blockly.Generator('LLVM');
+ Blockly.LLVM.ORDER_ATOMIC = 0;
+ Blockly.LLVM.ORDER_NONE = 99;
+
+ // --- Block-Definitionen für die Toolbox ---
+ Blockly.defineBlocksWithJsonArray([
+ {
+ "type": "host_log_integer",
+ "message0": "Logge Integer %1",
+ "args0": [
+ {
+ "type": "input_value",
+ "name": "VALUE",
+ "check": "Number"
+ }
+ ],
+ "previousStatement": null,
+ "nextStatement": null,
+ "colour": 290,
+ "tooltip": "Sendet einen Integer-Wert an den Delphi-Host.",
+ "helpUrl": ""
+ },
+ {
+ "type": "current_datetime_utc",
+ "message0": "Aktueller UTC-Zeitstempel",
+ "output": "DateTimeUTC",
+ "colour": 120,
+ "tooltip": "Liefert den aktuellen Zeitstempel in UTC.",
+ "helpUrl": ""
+ },
+ {
+ "type": "get_datetime_component",
+ "message0": "Hole %1 von Zeitstempel %2 in Zeitzone %3",
+ "args0": [
+ {
+ "type": "field_dropdown",
+ "name": "COMPONENT",
+ "options": [
+ ["Jahr", "YEAR"],
+ ["Monat", "MONTH"],
+ ["Tag", "DAY"],
+ ["Stunde", "HOUR"],
+ ["Minute", "MINUTE"],
+ ["Sekunde", "SECOND"]
+ ]
+ },
+ {
+ "type": "input_value",
+ "name": "DATETIME",
+ "check": "DateTimeUTC"
+ },
+ {
+ "type": "field_dropdown",
+ "name": "TIMEZONE",
+ "options": [
+ ["UTC", "UTC"],
+ ["ET (New York)", "ET"],
+ ["WET (London)", "WET"],
+ ["CET (Frankfurt)", "CET"],
+ ["AEST (Sydney)", "AEST"],
+ ["JST (Tokyo)", "JST"]
+ ]
+ }
+ ],
+ "output": "Number",
+ "colour": 120,
+ "tooltip": "Extrahiert eine Komponente (Jahr, Monat, etc.) aus einem UTC-Zeitstempel und konvertiert sie in die angegebene Zeitzone.",
+ "helpUrl": ""
+ }
+ ]);
+
+ // --- Generator-Implementierungen ---
+
+ Blockly.LLVM.regCounter = 0;
+ Blockly.LLVM.newReg = function() {
+ return '%' + (Blockly.LLVM.regCounter++);
+ };
+
+ Blockly.LLVM.workspaceToCode = function(workspace) {
+ Blockly.LLVM.regCounter = 1;
+ Blockly.LLVM.generatedStrings = new Set();
+ Blockly.LLVM.globalDeclarations = '';
+ Blockly.LLVM.functionDeclarations = '';
+
+ const allVariables = workspace.getAllVariables();
+ let varAllocations = '';
+ if (allVariables.length > 0) {
+ allVariables.forEach(v => {
+ const safeVarName = v.name.replace(/ /g, '_');
+ varAllocations += ` @${safeVarName} = common global i32 0\n`;
+ });
+ }
+
+ const topBlock = workspace.getTopBlocks(true)[0];
+ const code = topBlock ? Blockly.LLVM.blockToCode(topBlock) : '';
+
+ let moduleCode = `target triple = "x86_64-pc-windows-msvc"\n\n`;
+
+ moduleCode += `; Definition des DateTimeUTC-Structs\n`;
+ moduleCode += `%struct.DateTimeUTC = type { i32, i32, i32, i32, i32, i32 }\n\n`;
+
+ if (Blockly.LLVM.globalDeclarations) {
+ moduleCode += '; Global string constants for timezones\n';
+ moduleCode += Blockly.LLVM.globalDeclarations + '\n';
+ }
+
+ moduleCode += `; Host Callback Declarations\n`;
+ moduleCode += `declare void @get_current_datetime_utc(%struct.DateTimeUTC*)\n`;
+ moduleCode += `declare i32 @get_datetime_component_in_zone(%struct.DateTimeUTC*, i32, i8*)\n`;
+
+ if (Blockly.LLVM.functionDeclarations) {
+ moduleCode += Blockly.LLVM.functionDeclarations + '\n';
+ }
+
+ moduleCode += `@gLogIntProc = common global void (i32)* null\n`;
+ moduleCode += `@gGetCurrentDateTimeUTCProc = common global void (%struct.DateTimeUTC*)* null\n`;
+ moduleCode += `@gGetComponentInZoneProc = common global i32 (%struct.DateTimeUTC*, i32, i8*)* null\n\n`;
+
+
+ if (varAllocations) {
+ moduleCode += '; Global Variables\n';
+ moduleCode += varAllocations + '\n';
+ }
+
+ moduleCode += 'define dllexport void @StarteLogik(void (i32)* %LogIntProc, void (%struct.DateTimeUTC*)* %GetCurrentDateTimeUTCProc, i32 (%struct.DateTimeUTC*, i32, i8*)* %GetComponentInZoneProc) {\n';
+ moduleCode += 'entry:\n';
+ moduleCode += ' store void (i32)* %LogIntProc, void (i32)** @gLogIntProc\n';
+ moduleCode += ' store void (%struct.DateTimeUTC*)* %GetCurrentDateTimeUTCProc, void (%struct.DateTimeUTC*)** @gGetCurrentDateTimeUTCProc\n';
+ moduleCode += ' store i32 (%struct.DateTimeUTC*, i32, i8*)* %GetComponentInZoneProc, i32 (%struct.DateTimeUTC*, i32, i8*)** @gGetComponentInZoneProc\n\n';
+
+ moduleCode += code.split('\n').map(line => line ? ' ' + line : '').join('\n');
+ moduleCode += '\n ret void\n';
+ moduleCode += '}\n';
+ return moduleCode;
+ };
+
+ Blockly.LLVM.scrub_ = function(block, code) {
+ const nextBlock = block.nextConnection && block.nextConnection.targetBlock();
+ const nextCode = nextBlock ? Blockly.LLVM.blockToCode(nextBlock) : '';
+ return code + nextCode;
+ };
+
+ Blockly.LLVM.forBlock['variables_set'] = function(block) {
+ const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
+ const value = Blockly.LLVM.valueToCode(block, 'VALUE', Blockly.LLVM.ORDER_ATOMIC) || '0';
+ return `store i32 ${value}, i32* @${varName}\n`;
+ };
+
+ Blockly.LLVM.forBlock['math_change'] = function(block) {
+ const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
+ const delta = Blockly.LLVM.valueToCode(block, 'DELTA', Blockly.LLVM.ORDER_ATOMIC) || '0';
+
+ const loadReg = Blockly.LLVM.newReg();
+ const addReg = Blockly.LLVM.newReg();
+
+ let code = '';
+ code += `${loadReg} = load i32, i32* @${varName}\n`;
+ code += `${addReg} = add nsw i32 ${loadReg}, ${delta}\n`;
+ code += `store i32 ${addReg}, i32* @${varName}\n`;
+ return code;
+ };
+
+ Blockly.LLVM.forBlock['variables_get'] = function(block) {
+ const varName = block.workspace.getVariableById(block.getFieldValue('VAR')).name.replace(/ /g, '_');
+ return ['@' + varName, Blockly.LLVM.ORDER_ATOMIC];
+ };
+
+ Blockly.LLVM.forBlock['math_number'] = function(block) {
+ return [String(block.getFieldValue('NUM')), Blockly.LLVM.ORDER_ATOMIC];
+ };
+
+ Blockly.LLVM.forBlock['host_log_integer'] = function(block) {
+ const valueCode = Blockly.LLVM.valueToCode(block, 'VALUE', Blockly.LLVM.ORDER_ATOMIC) || '0';
+
+ let valueReg;
+ let code = '';
+
+ if (valueCode.startsWith('@')) {
+ valueReg = Blockly.LLVM.newReg();
+ code += `${valueReg} = load i32, i32* ${valueCode}\n`;
+ } else if (valueCode.startsWith('%')) {
+ valueReg = valueCode;
+ } else {
+ valueReg = valueCode;
+ }
+
+ const logPtrReg = Blockly.LLVM.newReg();
+ code += `${logPtrReg} = load void (i32)*, void (i32)** @gLogIntProc\n`;
+ code += `call void ${logPtrReg}(i32 ${valueReg})\n`;
+ return code;
+ };
+
+ Blockly.LLVM.forBlock['current_datetime_utc'] = function(block) {
+ const structPtrReg = Blockly.LLVM.newReg();
+ const getUtcProcPtrReg = Blockly.LLVM.newReg();
+
+ let code = `
+ ${structPtrReg} = alloca %struct.DateTimeUTC, align 8
+ ${getUtcProcPtrReg} = load void (%struct.DateTimeUTC*)*, void (%struct.DateTimeUTC*)** @gGetCurrentDateTimeUTCProc\n
+ call void ${getUtcProcPtrReg}(%struct.DateTimeUTC* ${structPtrReg})
+ `;
+
+ return [code + structPtrReg, Blockly.LLVM.ORDER_ATOMIC];
+ };
+
+ Blockly.LLVM.forBlock['get_datetime_component'] = function(block) {
+ const datetimePtr = Blockly.LLVM.valueToCode(block, 'DATETIME', Blockly.LLVM.ORDER_ATOMIC) || 'null';
+ const component = block.getFieldValue('COMPONENT');
+ const timezone = block.getFieldValue('TIMEZONE');
+
+ const timezoneGlobalName = `@.str.timezone_${timezone.replace(/[^a-zA-Z0-9_]/g, '')}`;
+ const timezoneStringLength = new TextEncoder().encode(timezone).length + 1;
+
+ if (!Blockly.LLVM.generatedStrings.has(timezoneGlobalName)) {
+ Blockly.LLVM.globalDeclarations += `${timezoneGlobalName} = private unnamed_addr constant [${timezoneStringLength} x i8] c"${timezone}\\00", align 1\n`;
+ Blockly.LLVM.generatedStrings.add(timezoneGlobalName);
+ }
+
+ let componentIndex = 0;
+ switch (component) {
+ case 'YEAR': componentIndex = 0; break;
+ case 'MONTH': componentIndex = 1; break;
+ case 'DAY': componentIndex = 2; break;
+ case 'HOUR': componentIndex = 3; break;
+ case 'MINUTE': componentIndex = 4; break;
+ case 'SECOND': componentIndex = 5; break;
+ }
+
+ const resultReg = Blockly.LLVM.newReg();
+ const timezoneStringPtrReg = Blockly.LLVM.newReg();
+ const getComponentProcPtrReg = Blockly.LLVM.newReg();
+
+ let code = `
+ ${timezoneStringPtrReg} = getelementptr inbounds [${timezoneStringLength} x i8], [${timezoneStringLength} x i8]* ${timezoneGlobalName}, i64 0, i64 0
+ ${getComponentProcPtrReg} = load i32 (%struct.DateTimeUTC*, i32, i8*)*, i32 (%struct.DateTimeUTC*, i32, i8*)** @gGetComponentInZoneProc\n
+ ${resultReg} = call i32 ${getComponentProcPtrReg}(%struct.DateTimeUTC* ${datetimePtr}, i32 ${componentIndex}, i8* ${timezoneStringPtrReg})
+ `;
+
+ return [code + resultReg, Blockly.LLVM.ORDER_ATOMIC];
+ };
+
+ const toolboxXml = `
+
+
+
+
+
+ 1
+
+
+
+
+
+
+
+
+
+ `;
+
+ workspace = Blockly.inject('blocklyDiv', {
+ toolbox: toolboxXml,
+ zoom: {
+ controls: true,
+ wheel: true,
+ startScale: 1.0,
+ maxScale: 3,
+ minScale: 0.3,
+ scaleSpeed: 1.2
+ },
+ trashcan: true,
+ maxBlocks: 500,
+ scrollbars: true,
+ grid: {
+ spacing: 25,
+ length: 3,
+ colour: '#eee',
+ snap: true
+ },
+ comments: true,
+ disable: true,
+ collapse: true,
+ readOnly: false
+ });
+
+ // --- Code-Generierungs- und Post-Funktion (angepasst, um vorher zu speichern) ---
+ function generateAndPostCode() {
+ // 1. Arbeitsbereich speichern
+ const state = Blockly.serialization.workspaces.save(workspace);
+ localStorage.setItem('blocklyWorkspace', JSON.stringify(state));
+ // Optional: Konsolenmeldung zur automatischen Speicherung
+ // console.log("Arbeitsbereich automatisch gespeichert vor Code-Generierung.");
+
+ // 2. Code generieren
+ const code = Blockly.LLVM.workspaceToCode(workspace);
+
+ // 3. Code posten oder anzeigen
+ if (isWebView) {
+ if (window.chrome && window.chrome.webview) {
+ window.chrome.webview.postMessage(code);
+ }
+ } else {
+ document.getElementById('codeOutput').value = code;
+ console.log("Code in Konsole ausgegeben (nicht im WebView):");
+ console.log(code);
+ }
+ }
+ window.generateAndPostCode = generateAndPostCode; // Exponiere für Buttons
+
+ window.saveWorkspace = function() {
+ // Diese Funktion kann den Arbeitsbereich manuell speichern und einen Alert anzeigen
+ const state = Blockly.serialization.workspaces.save(workspace);
+ localStorage.setItem('blocklyWorkspace', JSON.stringify(state));
+ alert('Arbeitsbereich gespeichert!');
+ }
+ window.loadWorkspace = function() { const stateString = localStorage.getItem('blocklyWorkspace'); if (!stateString) { return; } const state = JSON.parse(stateString); Blockly.serialization.workspaces.load(state, workspace); }
+
+ // --- Dynamische Code-Aktualisierung / Posten (ruft generateAndPostCode auf) ---
+ function handleCodeUpdate(event) {
+ if (event.isUiEvent) return; // Nur Änderungen durch Blöcke, nicht UI-Interaktionen
+ generateAndPostCode(); // Dies triggert jetzt sowohl Speichern als auch Generieren/Posten
+ }
+ workspace.addChangeListener(handleCodeUpdate);
+ loadWorkspace();
+
+ // --- Bedingte UI-Elemente und Splitter-Logik ---
+ const outputContainer = document.getElementById('outputContainer');
+ const blocklyDiv = document.getElementById('blocklyDiv');
+
+ if (isWebView) {
+ // Wenn im WebView, outputContainer bleibt ausgeblendet (CSS default: display: none;)
+ // BlocklyDiv die gesamte Breite geben
+ blocklyDiv.style.width = '100%';
+ // Blockly-Workspace an neue Größe anpassen, mit einer kleinen Verzögerung für WebView
+ setTimeout(function() {
+ Blockly.svgResize(workspace);
+ }, 100); // 100ms Verzögerung, kann bei Bedarf angepasst werden.
+
+ // Entferne die Schaltflächen "Speichern" und "Laden", wenn im WebView
+ // da die Speicherung automatisch erfolgt und der Host den Code direkt bekommt.
+ const buttonBar = document.querySelector('.button-bar');
+ if (buttonBar) {
+ const saveButton = buttonBar.querySelector('button[onclick="saveWorkspace()"]');
+ const loadButton = buttonBar.querySelector('button[onclick="loadWorkspace()"]');
+ if (saveButton) saveButton.remove();
+ if (loadButton) loadButton.remove();
+ // Eventuell auch den "Code generieren und posten" Button entfernen, da es automatisch passiert
+ // oder umbenennen in "Aktualisieren" / "Neu senden"
+ const postButton = buttonBar.querySelector('button[onclick="generateAndPostCode()"]');
+ if (postButton) postButton.remove(); // Oder postButton.textContent = "Code senden";
+ }
+
+ } else {
+ // Wenn NICHT im WebView, outputContainer einblenden und Splitter-Logik initialisieren
+ outputContainer.style.display = 'flex'; // Einblenden als Flex-Container
+
+ const outputArea = document.getElementById('outputArea');
+ const splitter = document.getElementById('splitter');
+ const container = document.getElementById('container');
+
+ let isDragging = false;
+
+ splitter.addEventListener('mousedown', function(e) {
+ isDragging = true;
+ document.body.style.userSelect = 'none';
+ document.body.style.cursor = 'ew-resize';
+ });
+
+ document.addEventListener('mousemove', function(e) {
+ if (!isDragging) return;
+
+ const containerRect = container.getBoundingClientRect();
+ const splitterWidth = splitter.offsetWidth;
+ const outputAreaMarginLeft = parseInt(window.getComputedStyle(outputArea).marginLeft);
+
+ const totalContentWidth = containerRect.width - splitterWidth - outputAreaMarginLeft;
+ let newBlocklyWidth = e.clientX - containerRect.left;
+
+ const minBlocklyWidth = parseFloat(window.getComputedStyle(blocklyDiv).minWidth);
+ const minOutputAreaWidth = parseFloat(window.getComputedStyle(outputArea).minWidth);
+
+ if (newBlocklyWidth < minBlocklyWidth) {
+ newBlocklyWidth = minBlocklyWidth;
+ }
+
+ let newOutputAreaWidth = totalContentWidth - newBlocklyWidth;
+
+ if (newOutputAreaWidth < minOutputAreaWidth) {
+ newOutputAreaWidth = minOutputAreaWidth;
+ newBlocklyWidth = totalContentWidth - newOutputAreaWidth;
+ if (newBlocklyWidth < minBlocklyWidth) {
+ newBlocklyWidth = minBlocklyWidth;
+ }
+ }
+
+ blocklyDiv.style.width = `${newBlocklyWidth}px`;
+ outputArea.style.width = `${newOutputAreaWidth}px`;
+
+ Blockly.svgResize(workspace);
+ });
+
+ document.addEventListener('mouseup', function() {
+ isDragging = false;
+ document.body.style.userSelect = '';
+ document.body.style.cursor = '';
+ });
+
+ // Initiales Resize für Nicht-WebView: Setzt die initialen Breiten
+ // Basierend auf der Startbreite der outputArea (500px)
+ const initialOutputAreaWidth = 500; // Aus CSS initialer Wert
+ const totalFlexContentWidth = container.offsetWidth - splitter.offsetWidth - parseInt(window.getComputedStyle(outputArea).marginLeft);
+ let initialBlocklyWidth = totalFlexContentWidth - initialOutputAreaWidth;
+
+ if (initialBlocklyWidth < minBlocklyWidth) {
+ initialBlocklyWidth = minBlocklyWidth;
+ outputArea.style.width = `${totalFlexContentWidth - initialBlocklyWidth}px`;
+ } else {
+ outputArea.style.width = `${initialOutputAreaWidth}px`;
+ }
+ blocklyDiv.style.width = `${initialBlocklyWidth}px`;
+
+ Blockly.svgResize(workspace);
+ }
+};
diff --git a/Blockly/style.css b/Blockly/style.css
new file mode 100644
index 0000000..6ff1805
--- /dev/null
+++ b/Blockly/style.css
@@ -0,0 +1,116 @@
+/* style.css */
+
+/* Global box-sizing für konsistente Größenberechnung */
+* {
+ box-sizing: border-box;
+}
+
+/* Allgemeine Styles für html und body, um den gesamten Viewport zu füllen */
+html, body {
+ margin: 0;
+ padding: 0;
+ height: 100%; /* Stellt sicher, dass html und body die volle Viewport-Höhe einnehmen */
+ font-family: sans-serif;
+ overflow: hidden; /* Verhindert Scrollbalken auf der Hauptebene des Bodys */
+ background-color: #F8F8F8; /* Optionale Hintergrundfarbe für den gesamten Body, falls gewünscht */
+}
+
+/* Body als Flex-Container, um Inhalte vertikal zu stapeln */
+body {
+ display: flex;
+ flex-direction: column;
+}
+
+/* Optional: Style für die Überschrift im Output-Bereich und allgemeine Überschriften/Paragraphen */
+h1, h2, p {
+ margin: 0;
+ padding: 10px 0; /* Beispiel: Etwas vertikale Polsterung, keine horizontalen Ränder */
+ text-align: center; /* Überschriften zentrieren */
+}
+
+/* Styling für die Button-Leiste */
+.button-bar {
+ margin-bottom: 0; /* Rand unten entfernen */
+ padding: 10px 0 0 0; /* Polsterung anpassen, um oberen Rand zu entfernen */
+ text-align: center; /* Buttons zentrieren */
+}
+
+.button-bar button {
+ margin: 0 5px; /* Kleiner Abstand zwischen den Buttons */
+ padding: 8px 15px;
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ background-color: #e0e0e0;
+ cursor: pointer;
+}
+
+.button-bar button:hover {
+ background-color: #d0d0d0;
+}
+
+/* Haupt-Container für Blockly-Workspace und Output-Bereich */
+#container {
+ display: flex; /* Machen Sie den Container zu einem Flex-Container, um die Kinder nebeneinander anzuordnen */
+ flex-grow: 1; /* Lässt den Container den restlichen vertikalen Platz füllen */
+ padding: 0; /* Polsterung um den Inhalt herum vollständig entfernen */
+ box-sizing: border-box; /* Stellt sicher, dass Padding in der Größe enthalten ist */
+}
+
+/* Blockly-Workspace Bereich */
+#blocklyDiv {
+ flex-grow: 1; /* Lässt BlocklyDiv den maximalen horizontalen Platz einnehmen */
+ min-width: 200px; /* Mindestbreite für Blockly, damit es nicht zu klein wird */
+ height: 100%; /* Füllt die Höhe des #container */
+ background-color: #FFF8E1; /* Sehr helles Beige für den Blockly-Hintergrund des Containers */
+ margin: 0; /* Rand entfernen */
+}
+
+/* WICHTIG: Regel für den Blockly SVG-Hintergrund */
+#blocklyDiv .blocklySvg {
+ background-color: #FFF8E1; /* Hintergrundfarbe für das von Blockly generierte SVG-Element */
+}
+
+/* Optional: Sicherstellen, dass Blockly-Scrollbalken über anderen Elementen liegen */
+#blocklyDiv .blocklyScrollbarHorizontal,
+#blocklyDiv .blocklyScrollbarVertical {
+ z-index: 100;
+}
+
+/* Flex-Container für Splitter und Output-Bereich */
+#outputContainer {
+ display: none; /* Standardmäßig ausgeblendet, wird bei Bedarf von JS eingeblendet */
+ flex-shrink: 0; /* Verhindert, dass dieser Container schrumpft, wenn nicht im WebView */
+ flex-basis: auto; /* Initial flexible Basis */
+}
+
+/* Splitter-Element */
+#splitter {
+ width: 8px; /* Breite des Splitters */
+ background-color: #ccc; /* Farbe des Splitters */
+ cursor: ew-resize; /* Zeigt den "Ost-West-Größenänderung"-Cursor */
+ flex-shrink: 0; /* Verhindert, dass der Splitter schrumpft */
+ margin-left: 0; /* Abstand zum Blockly-Bereich entfernen */
+ margin-right: 0; /* Abstand zum Output-Bereich entfernen */
+}
+
+/* Output-Bereich (mit Code-Textarea) */
+#outputArea {
+ display: flex;
+ flex-direction: column; /* Überschrift und Textarea vertikal stapeln */
+ min-width: 200px; /* Mindestbreite für die OutputArea */
+ width: 500px; /* Startbreite für den Output-Bereich, wird von JS überschrieben */
+ box-sizing: border-box;
+ margin: 0; /* Rand entfernen */
+}
+
+/* Textarea für den generierten Code */
+#codeOutput {
+ flex-grow: 1; /* Lässt die Textarea die verbleibende Höhe in outputArea füllen */
+ font-family: 'Courier New', Courier, monospace;
+ font-size: 14px;
+ white-space: pre-wrap;
+ border: none; /* Deaktiviert den Rand der Textarea */
+ resize: none; /* Deaktiviert die eingebaute Resize-Funktion der Textarea */
+ overflow: auto; /* Notwendig, damit Scrollbalken erscheinen, wenn der Inhalt die Größe überschreitet */
+ padding: 10px; /* Optional: Innenabstand für den Text, damit er nicht direkt am Rand klebt */
+}