From 6210e9c99b53bd2feef57553366760c5b2cef492 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Mon, 10 Nov 2025 20:02:11 +0100 Subject: [PATCH 1/2] working keydown --- README.md | 146 +++++-- additional/env.js | 421 +++++++++++++------- examples/CompleteEventHandling/main.cpp | 2 - examples/EnhancedEventHandling/main.cpp | 63 +++ examples/EnhancedEventHandling/project.json | 17 + examples/EnhancedEventHandling/run.sh | 1 + examples/HelloWorld/main.cpp | 2 +- interfaces/Crafter.CppDOM-Bindings.cppm | 274 ++++++++++--- interfaces/Crafter.CppDOM-EventTypes.cppm | 73 ++++ interfaces/Crafter.CppDOM-HtmlElement.cppm | 370 ++++++++++------- interfaces/Crafter.CppDOM.cppm | 3 +- project.json | 4 +- 12 files changed, 975 insertions(+), 401 deletions(-) create mode 100644 examples/EnhancedEventHandling/main.cpp create mode 100644 examples/EnhancedEventHandling/project.json create mode 100755 examples/EnhancedEventHandling/run.sh create mode 100644 interfaces/Crafter.CppDOM-EventTypes.cppm diff --git a/README.md b/README.md index 4cdd545..9893b6c 100644 --- a/README.md +++ b/README.md @@ -58,66 +58,162 @@ Save and close, then run ``crafter-build build executable && caddy file-server - This sample can also be viewed in the [HelloElement example](https://forgejo.catcrafts.net/Catcrafts/Crafter.CppDOM/src/branch/master/examples) -## New Event Handling Capabilities +## Enhanced Event Handling Capabilities -The library now supports comprehensive event handling for modern web applications: +The library now supports comprehensive event handling with rich event data for modern web applications: ### Mouse Events - `AddClickListener()` - Handles click events - `AddMouseOverListener()` - Handles mouse over events - `AddMouseOutListener()` - Handles mouse out events - `AddMouseMoveListener()` - Handles mouse move events +- `AddMouseDownListener()` - Handles mouse down events +- `AddMouseUpListener()` - Handles mouse up events ### Focus Events - `AddFocusListener()` - Handles focus events - `AddBlurListener()` - Handles blur events ### Keyboard Events -- `AddKeyDownListener()` - Handles key down events -- `AddKeyUpListener()` - Handles key up events -- `AddKeyPressListener()` - Handles key press events +- `AddKeyDownListener()` - Handles key down events with event data +- `AddKeyUpListener()` - Handles key up events with event data +- `AddKeyPressListener()` - Handles key press events with event data ### Form Events -- `AddChangeListener()` - Handles change events +- `AddChangeListener()` - Handles change events with event data - `AddSubmitListener()` - Handles form submit events -- `AddInputListener()` - Handles input events +- `AddInputListener()` - Handles input events with event data ### Window Events - `AddLoadListener()` - Handles page load events -- `AddErrorListener()` - Handles error events -- `AddResizeListener()` - Handles window resize events -- `AddScrollListener()` - Handles scroll events +- `AddErrorListener()` - Handles error events with event data +- `AddResizeListener()` - Handles window resize events with event data +- `AddScrollListener()` - Handles scroll events with event data ### Context Menu Events -- `AddContextMenuListener()` - Handles context menu events +- `AddContextMenuListener()` - Handles context menu events with event data ### Drag and Drop Events -- `AddDragStartListener()` - Handles drag start events -- `AddDragEndListener()` - Handles drag end events -- `AddDropListener()` - Handles drop events +- `AddDragStartListener()` - Handles drag start events with event data +- `AddDragEndListener()` - Handles drag end events with event data +- `AddDropListener()` - Handles drop events with event data +- `AddDragOverListener()` - Handles drag over events with event data +- `AddDragEnterListener()` - Handles drag enter events with event data +- `AddDragLeaveListener()` - Handles drag leave events with event data + +### Wheel Events +- `AddWheelListener()` - Handles wheel events with event data + +### Example Usage with Event Data -Example usage: ```cpp import Crafter.CppDOM; -using namespace Crafter::CppDOM; +using namespace Crafter; int main(){ HtmlElement button("myButton"); HtmlElement input("textInput"); - // Handle click event + // Handle click event with position data button.AddClickListener([]() { - // Handle button click + // Simple click handler without event data }); - // Handle keyboard events - input.AddKeyDownListener([]() { - // Handle key press + // Handle keyboard events with rich event data + input.AddKeyDownListener([](Crafter::CppDOM::EventTypes::KeyboardEvent event) { + // Access key information + if (event.key == "Enter") { + // Handle Enter key specifically + } + // Check modifier keys + if (event.ctrlKey) { + // Handle Ctrl+key combinations + } }); - // Handle input changes - input.AddInputListener([]() { - // Handle input changes + // Handle input changes with event data + input.AddInputListener([](Crafter::CppDOM::EventTypes::InputEvent event) { + // Access input data + std::string data = event.data; + bool isComposing = event.isComposing; + }); + + // Handle mouse movements with coordinates + button.AddMouseMoveListener([](Crafter::CppDOM::EventTypes::MouseEvent event) { + // Access mouse position + double x = event.clientX; + double y = event.clientY; + }); + + // Handle form changes with value + input.AddChangeListener([](Crafter::CppDOM::EventTypes::ChangeEvent event) { + // Access the new value + std::string value = event.value; + }); + + // Handle window resize with dimensions + button.AddResizeListener([](Crafter::CppDOM::EventTypes::ResizeEvent event) { + // Access window dimensions + unsigned int width = event.width; + unsigned int height = event.height; }); } -``` \ No newline at end of file +``` + +### Event Data Structures + +The library provides specific event data structures for different event types: + +#### KeyboardEvent +- `std::string key` - The key value +- `std::string code` - The physical key code +- `int keyCode` - Legacy key code +- `bool altKey` - Whether Alt key was pressed +- `bool ctrlKey` - Whether Ctrl key was pressed +- `bool shiftKey` - Whether Shift key was pressed +- `bool metaKey` - Whether Meta key was pressed + +#### MouseEvent +- `double clientX` - X coordinate relative to viewport +- `double clientY` - Y coordinate relative to viewport +- `double screenX` - X coordinate relative to screen +- `double screenY` - Y coordinate relative to screen +- `int button` - Which mouse button was pressed +- `int buttons` - Which mouse buttons were pressed +- `bool altKey` - Whether Alt key was pressed +- `bool ctrlKey` - Whether Ctrl key was pressed +- `bool shiftKey` - Whether Shift key was pressed +- `bool metaKey` - Whether Meta key was pressed + +#### InputEvent +- `std::string data` - The input data +- `bool isComposing` - Whether input is in composition mode + +#### ChangeEvent +- `std::string value` - The new value + +#### ResizeEvent +- `unsigned int width` - Window width +- `unsigned int height` - Window height + +#### ScrollEvent +- `double scrollX` - Horizontal scroll position +- `double scrollY` - Vertical scroll position + +#### ErrorEvent +- `std::string message` - Error message +- `std::string filename` - File where error occurred +- `unsigned int lineno` - Line number +- `unsigned int colno` - Column number + +#### DragEvent +- All MouseEvent properties plus: +- `double offsetX` - X offset from drag start +- `double offsetY` - Y offset from drag start + +#### WheelEvent +- All MouseEvent properties plus: +- `double deltaX` - Horizontal scroll amount +- `double deltaY` - Vertical scroll amount +- `double deltaZ` - Depth scroll amount +- `int deltaMode` - Scroll mode \ No newline at end of file diff --git a/additional/env.js b/additional/env.js index 3ae3309..dbf94e6 100644 --- a/additional/env.js +++ b/additional/env.js @@ -29,6 +29,19 @@ function freeJs(ptr) { jsmemory.delete(ptr); } +function writeStringToWasm(str) { + const encoder = new TextEncoder(); + const encoded = encoder.encode(str + '\0'); + const len = encoded.length; + + const { WasmAlloc } = window.crafter_webbuild_wasi.instance.exports; + const ptr = WasmAlloc(len); + const memView = new Uint8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, ptr, len); + memView.set(encoded); + + return ptr; +} + function getElementById(id, idLenght) { const obj = document.getElementById(decoder.decode(new Int8Array(window.crafter_webbuild_wasi.instance.exports.memory.buffer, id, idLenght))); jsmemory.set(++memorycounter, obj); @@ -42,427 +55,523 @@ function setInnerHTML(ptr, html, htmlLenght) { // Event handler registration functions function addClickListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + // Create a handler that will trigger a notification to C++ - const handler = function(event) { + const handler = function (event) { const { ExecuteClickHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteClickHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}`, handler); - + element.addEventListener("click", handler); } function removeClickListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}`); - + element.removeEventListener("click", handler); eventHandlers.delete(`${ptr}-${handlerID}`); } -// Add more event handlers for modern websites +// Mouse Events function addMouseOverListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteMouseOverHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteMouseOverHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-mouseover`, handler); element.addEventListener("mouseover", handler); } function removeMouseOverListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-mouseover`); - + element.removeEventListener("mouseover", handler); eventHandlers.delete(`${ptr}-${handlerID}-mouseover`); } function addMouseOutListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteMouseOutHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteMouseOutHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-mouseout`, handler); element.addEventListener("mouseout", handler); } function removeMouseOutListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-mouseout`); - + element.removeEventListener("mouseout", handler); eventHandlers.delete(`${ptr}-${handlerID}-mouseout`); } function addMouseMoveListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteMouseMoveHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteMouseMoveHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-mousemove`, handler); element.addEventListener("mousemove", handler); } function removeMouseMoveListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-mousemove`); - + element.removeEventListener("mousemove", handler); eventHandlers.delete(`${ptr}-${handlerID}-mousemove`); } +function addMouseDownListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteMouseDownHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteMouseDownHandler(handlerID); + }; + + eventHandlers.set(`${ptr}-${handlerID}-mousedown`, handler); + element.addEventListener("mousedown", handler); +} + +function removeMouseDownListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-mousedown`); + + element.removeEventListener("mousedown", handler); + eventHandlers.delete(`${ptr}-${handlerID}-mousedown`); +} + +function addMouseUpListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteMouseUpHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteMouseUpHandler(handlerID); + }; + + eventHandlers.set(`${ptr}-${handlerID}-mouseup`, handler); + element.addEventListener("mouseup", handler); +} + +function removeMouseUpListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-mouseup`); + + element.removeEventListener("mouseup", handler); + eventHandlers.delete(`${ptr}-${handlerID}-mouseup`); +} + +// Focus Events function addFocusListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteFocusHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteFocusHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-focus`, handler); element.addEventListener("focus", handler); } function removeFocusListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-focus`); - + element.removeEventListener("focus", handler); eventHandlers.delete(`${ptr}-${handlerID}-focus`); } function addBlurListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteBlurHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteBlurHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-blur`, handler); element.addEventListener("blur", handler); } function removeBlurListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-blur`); - + element.removeEventListener("blur", handler); eventHandlers.delete(`${ptr}-${handlerID}-blur`); } +// Keyboard Events function addKeyDownListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { - const { ExecuteKeyDownHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteKeyDownHandler(handlerID, event.key, event.code, event.keyCode); + + const handler = function (event) { + const { ExecuteKeyDownHandler, WasmFree } = window.crafter_webbuild_wasi.instance.exports; + const ptr = writeStringToWasm(event.key); + ExecuteKeyDownHandler(handlerID, ptr, event.keyCode, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + WasmFree(ptr); }; - + eventHandlers.set(`${ptr}-${handlerID}-keydown`, handler); element.addEventListener("keydown", handler); } function removeKeyDownListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-keydown`); - + element.removeEventListener("keydown", handler); eventHandlers.delete(`${ptr}-${handlerID}-keydown`); } function addKeyUpListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { - const { ExecuteKeyUpHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteKeyUpHandler(handlerID, event.key, event.code, event.keyCode); + + const handler = function (event) { + const { ExecuteKeyUpHandler, WasmFree } = window.crafter_webbuild_wasi.instance.exports; + const ptr = writeStringToWasm(event.key); + ExecuteKeyUpHandler(handlerID, ptr, event.keyCode, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + WasmFree(ptr); }; - + eventHandlers.set(`${ptr}-${handlerID}-keyup`, handler); element.addEventListener("keyup", handler); } function removeKeyUpListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-keyup`); - + element.removeEventListener("keyup", handler); eventHandlers.delete(`${ptr}-${handlerID}-keyup`); } function addKeyPressListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { - const { ExecuteKeyPressHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteKeyPressHandler(handlerID, event.key, event.code, event.keyCode); + + const handler = function (event) { + const { ExecuteKeyPressHandler, WasmFree } = window.crafter_webbuild_wasi.instance.exports; + const ptr = writeStringToWasm(event.key); + ExecuteKeyPressHandler(handlerID, ptr, event.keyCode, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + WasmFree(ptr); }; - + eventHandlers.set(`${ptr}-${handlerID}-keypress`, handler); element.addEventListener("keypress", handler); } function removeKeyPressListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-keypress`); - + element.removeEventListener("keypress", handler); eventHandlers.delete(`${ptr}-${handlerID}-keypress`); } function addChangeListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteChangeHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteChangeHandler(handlerID); + ExecuteChangeHandler(handlerID, event.target.value); }; - + eventHandlers.set(`${ptr}-${handlerID}-change`, handler); element.addEventListener("change", handler); } function removeChangeListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-change`); - + element.removeEventListener("change", handler); eventHandlers.delete(`${ptr}-${handlerID}-change`); } function addSubmitListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteSubmitHandler } = window.crafter_webbuild_wasi.instance.exports; ExecuteSubmitHandler(handlerID); }; - + eventHandlers.set(`${ptr}-${handlerID}-submit`, handler); element.addEventListener("submit", handler); } function removeSubmitListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-submit`); - + element.removeEventListener("submit", handler); eventHandlers.delete(`${ptr}-${handlerID}-submit`); } function addInputListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteInputHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteInputHandler(handlerID); + ExecuteInputHandler(handlerID, event.data || event.target.value, event.inputType === 'insertCompositionText'); }; - + eventHandlers.set(`${ptr}-${handlerID}-input`, handler); element.addEventListener("input", handler); } function removeInputListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-input`); - + element.removeEventListener("input", handler); eventHandlers.delete(`${ptr}-${handlerID}-input`); } -function addLoadListener(ptr, handlerID) { - const element = jsmemory.get(ptr); - - const handler = function(event) { - const { ExecuteLoadHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteLoadHandler(handlerID); - }; - - eventHandlers.set(`${ptr}-${handlerID}-load`, handler); - element.addEventListener("load", handler); -} - -function removeLoadListener(ptr, handlerID) { - const element = jsmemory.get(ptr); - - const handler = eventHandlers.get(`${ptr}-${handlerID}-load`); - - element.removeEventListener("load", handler); - eventHandlers.delete(`${ptr}-${handlerID}-load`); -} - -function addErrorListener(ptr, handlerID) { - const element = jsmemory.get(ptr); - - const handler = function(event) { - const { ExecuteErrorHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteErrorHandler(handlerID); - }; - - eventHandlers.set(`${ptr}-${handlerID}-error`, handler); - element.addEventListener("error", handler); -} - -function removeErrorListener(ptr, handlerID) { - const element = jsmemory.get(ptr); - - const handler = eventHandlers.get(`${ptr}-${handlerID}-error`); - - element.removeEventListener("error", handler); - eventHandlers.delete(`${ptr}-${handlerID}-error`); -} - function addResizeListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteResizeHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteResizeHandler(handlerID); + ExecuteResizeHandler(handlerID, window.innerWidth, window.innerHeight); }; - + eventHandlers.set(`${ptr}-${handlerID}-resize`, handler); element.addEventListener("resize", handler); } function removeResizeListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-resize`); - + element.removeEventListener("resize", handler); eventHandlers.delete(`${ptr}-${handlerID}-resize`); } function addScrollListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteScrollHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteScrollHandler(handlerID); + ExecuteScrollHandler(handlerID, window.scrollX, window.scrollY); }; - + eventHandlers.set(`${ptr}-${handlerID}-scroll`, handler); element.addEventListener("scroll", handler); } function removeScrollListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-scroll`); - + element.removeEventListener("scroll", handler); eventHandlers.delete(`${ptr}-${handlerID}-scroll`); } +// Context Menu Events function addContextMenuListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteContextMenuHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteContextMenuHandler(handlerID); + ExecuteContextMenuHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); }; - + eventHandlers.set(`${ptr}-${handlerID}-contextmenu`, handler); element.addEventListener("contextmenu", handler); } function removeContextMenuListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-contextmenu`); - + element.removeEventListener("contextmenu", handler); eventHandlers.delete(`${ptr}-${handlerID}-contextmenu`); } +// Drag and Drop Events function addDragStartListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteDragStartHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteDragStartHandler(handlerID); + ExecuteDragStartHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); }; - + eventHandlers.set(`${ptr}-${handlerID}-dragstart`, handler); element.addEventListener("dragstart", handler); } function removeDragStartListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-dragstart`); - + element.removeEventListener("dragstart", handler); eventHandlers.delete(`${ptr}-${handlerID}-dragstart`); } function addDragEndListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteDragEndHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteDragEndHandler(handlerID); + ExecuteDragEndHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); }; - + eventHandlers.set(`${ptr}-${handlerID}-dragend`, handler); element.addEventListener("dragend", handler); } function removeDragEndListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-dragend`); - + element.removeEventListener("dragend", handler); eventHandlers.delete(`${ptr}-${handlerID}-dragend`); } function addDropListener(ptr, handlerID) { const element = jsmemory.get(ptr); - - const handler = function(event) { + + const handler = function (event) { const { ExecuteDropHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteDropHandler(handlerID); + ExecuteDropHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); }; - + eventHandlers.set(`${ptr}-${handlerID}-drop`, handler); element.addEventListener("drop", handler); } function removeDropListener(ptr, handlerID) { const element = jsmemory.get(ptr); - + const handler = eventHandlers.get(`${ptr}-${handlerID}-drop`); - + element.removeEventListener("drop", handler); eventHandlers.delete(`${ptr}-${handlerID}-drop`); } +// Additional Drag Events +function addDragOverListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteDragOverHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteDragOverHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + }; + + eventHandlers.set(`${ptr}-${handlerID}-dragover`, handler); + element.addEventListener("dragover", handler); +} + +function removeDragOverListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-dragover`); + + element.removeEventListener("dragover", handler); + eventHandlers.delete(`${ptr}-${handlerID}-dragover`); +} + +function addDragEnterListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteDragEnterHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteDragEnterHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + }; + + eventHandlers.set(`${ptr}-${handlerID}-dragenter`, handler); + element.addEventListener("dragenter", handler); +} + +function removeDragEnterListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-dragenter`); + + element.removeEventListener("dragenter", handler); + eventHandlers.delete(`${ptr}-${handlerID}-dragenter`); +} + +function addDragLeaveListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteDragLeaveHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteDragLeaveHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + }; + + eventHandlers.set(`${ptr}-${handlerID}-dragleave`, handler); + element.addEventListener("dragleave", handler); +} + +function removeDragLeaveListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-dragleave`); + + element.removeEventListener("dragleave", handler); + eventHandlers.delete(`${ptr}-${handlerID}-dragleave`); +} + +// Wheel Event +function addWheelListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = function (event) { + const { ExecuteWheelHandler } = window.crafter_webbuild_wasi.instance.exports; + ExecuteWheelHandler(handlerID, event.deltaX, event.deltaY, event.deltaZ, event.deltaMode, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); + }; + + eventHandlers.set(`${ptr}-${handlerID}-wheel`, handler); + element.addEventListener("wheel", handler); +} + +function removeWheelListener(ptr, handlerID) { + const element = jsmemory.get(ptr); + + const handler = eventHandlers.get(`${ptr}-${handlerID}-wheel`); + + element.removeEventListener("wheel", handler); + eventHandlers.delete(`${ptr}-${handlerID}-wheel`); +} + let env = { freeJs: freeJs, getElementById: getElementById, @@ -475,6 +584,10 @@ let env = { removeMouseOutListener: removeMouseOutListener, addMouseMoveListener: addMouseMoveListener, removeMouseMoveListener: removeMouseMoveListener, + addMouseDownListener: addMouseDownListener, + removeMouseDownListener: removeMouseDownListener, + addMouseUpListener: addMouseUpListener, + removeMouseUpListener: removeMouseUpListener, addFocusListener: addFocusListener, removeFocusListener: removeFocusListener, addBlurListener: addBlurListener, @@ -491,10 +604,6 @@ let env = { removeSubmitListener: removeSubmitListener, addInputListener: addInputListener, removeInputListener: removeInputListener, - addLoadListener: addLoadListener, - removeLoadListener: removeLoadListener, - addErrorListener: addErrorListener, - removeErrorListener: removeErrorListener, addResizeListener: addResizeListener, removeResizeListener: removeResizeListener, addScrollListener: addScrollListener, @@ -507,6 +616,14 @@ let env = { removeDragEndListener: removeDragEndListener, addDropListener: addDropListener, removeDropListener: removeDropListener, + addWheelListener: addWheelListener, + removeWheelListener: removeWheelListener, + addDragOverListener: addDragOverListener, + removeDragOverListener: removeDragOverListener, + addDragEnterListener: addDragEnterListener, + removeDragEnterListener: removeDragEnterListener, + addDragLeaveListener: addDragLeaveListener, + removeDragLeaveListener: removeDragLeaveListener, } window.crafter_webbuild_env = env; \ No newline at end of file diff --git a/examples/CompleteEventHandling/main.cpp b/examples/CompleteEventHandling/main.cpp index e5ad748..396477d 100644 --- a/examples/CompleteEventHandling/main.cpp +++ b/examples/CompleteEventHandling/main.cpp @@ -7,8 +7,6 @@ HtmlElement* input = new HtmlElement("textInput"); HtmlElement* output = new HtmlElement("output"); int main(){ - - // Click event button->AddClickListener([&]() { output->SetInnerHTML("Button was clicked!"); diff --git a/examples/EnhancedEventHandling/main.cpp b/examples/EnhancedEventHandling/main.cpp new file mode 100644 index 0000000..8d7d864 --- /dev/null +++ b/examples/EnhancedEventHandling/main.cpp @@ -0,0 +1,63 @@ +import Crafter.CppDOM; +using namespace Crafter; +import std; + +HtmlElement* body = new HtmlElement("body", "
" + "

Enhanced Event Handling Demo

" + "" + "" + "" + "" + "
" + "
"); +HtmlElement* clickButton = new HtmlElement("clickButton"); +HtmlElement* mouseButton = new HtmlElement("mouseButton"); +HtmlElement* keyInput = new HtmlElement("keyInput"); +HtmlElement* changeInput = new HtmlElement("changeInput"); +HtmlElement* output = new HtmlElement("output"); + +int main(){ + // Click event - simple handler + clickButton->AddClickListener([&]() { + output->SetInnerHTML("

Simple click event triggered!

"); + }); + + // Mouse events with position data + // mouseButton->AddMouseMoveListener([&](MouseEvent event) { + // output->SetInnerHTML("

Mouse moved to: (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")

"); + // }); + + // Keyboard events with rich data + keyInput->AddKeyDownListener([&](KeyboardEvent event) { + std::string keyInfo = std::format("

Key pressed: {}

", event.key); + if (event.ctrlKey) keyInfo += "

Ctrl key pressed

"; + if (event.shiftKey) keyInfo += "

Shift key pressed

"; + if (event.altKey) keyInfo += "

Alt key pressed

"; + output->SetInnerHTML(keyInfo); + }); + + // // Input event with data + // keyInput->AddInputListener([&](InputEvent event) { + // output->SetInnerHTML(std::format("

Input data: {} (composing: {})

", event.data, event.isComposing)); + // }); + + // Change event with value + changeInput->AddChangeListener([&](ChangeEvent event) { + output->SetInnerHTML("

Input value changed to: '" + event.value + "'

"); + }); + + // Context menu with position + mouseButton->AddContextMenuListener([&](MouseEvent event) { + output->SetInnerHTML("

Context menu at: (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")

"); + }); + + // Resize event + body->AddResizeListener([&](ResizeEvent event) { + output->SetInnerHTML("

Window resized to: " + std::to_string(event.width) + "x" + std::to_string(event.height) + "

"); + }); + + // Scroll event + body->AddScrollListener([&](ScrollEvent event) { + output->SetInnerHTML("

Scrolled to: (" + std::to_string(event.scrollX) + ", " + std::to_string(event.scrollY) + ")

"); + }); +} \ No newline at end of file diff --git a/examples/EnhancedEventHandling/project.json b/examples/EnhancedEventHandling/project.json new file mode 100644 index 0000000..9750e20 --- /dev/null +++ b/examples/EnhancedEventHandling/project.json @@ -0,0 +1,17 @@ +{ + "name": "main", + "configurations": [ + { + "name": "executable", + "implementations": ["main"], + "target": "wasm32-wasi", + "debug" : true, + "dependencies": [ + { + "path":"../../project.json", + "configuration":"lib-debug" + } + ] + } + ] +} \ No newline at end of file diff --git a/examples/EnhancedEventHandling/run.sh b/examples/EnhancedEventHandling/run.sh new file mode 100755 index 0000000..e706621 --- /dev/null +++ b/examples/EnhancedEventHandling/run.sh @@ -0,0 +1 @@ +caddy file-server --listen :8080 --root bin/executable \ No newline at end of file diff --git a/examples/HelloWorld/main.cpp b/examples/HelloWorld/main.cpp index 1fe57d6..b485511 100644 --- a/examples/HelloWorld/main.cpp +++ b/examples/HelloWorld/main.cpp @@ -1,5 +1,5 @@ import Crafter.CppDOM; -using namespace Crafter::CppDOM::Bindings; +using namespace Crafter::CppDOMBindings; int main(){ void* body = GetElementById("body"); diff --git a/interfaces/Crafter.CppDOM-Bindings.cppm b/interfaces/Crafter.CppDOM-Bindings.cppm index 6177fd7..3c76173 100644 --- a/interfaces/Crafter.CppDOM-Bindings.cppm +++ b/interfaces/Crafter.CppDOM-Bindings.cppm @@ -20,8 +20,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.CppDOM:Bindings; import std; +import :EventTypes; -export namespace Crafter::CppDOM::Bindings { +export namespace Crafter::CppDOMBindings { int clickHandlerMaxId = 0; std::unordered_map>* clickHandlers = new std::unordered_map>(); @@ -34,6 +35,12 @@ export namespace Crafter::CppDOM::Bindings { int mouseMoveHandlerMaxId = 0; std::unordered_map>* mouseMoveHandlers = new std::unordered_map>(); + int mouseDownHandlerMaxId = 0; + std::unordered_map>* mouseDownHandlers = new std::unordered_map>(); + + int mouseUpHandlerMaxId = 0; + std::unordered_map>* mouseUpHandlers = new std::unordered_map>(); + int focusHandlerMaxId = 0; std::unordered_map>* focusHandlers = new std::unordered_map>(); @@ -41,47 +48,53 @@ export namespace Crafter::CppDOM::Bindings { std::unordered_map>* blurHandlers = new std::unordered_map>(); int keyDownHandlerMaxId = 0; - std::unordered_map>* keyDownHandlers = new std::unordered_map>(); + std::unordered_map>* keyDownHandlers = new std::unordered_map>(); int keyUpHandlerMaxId = 0; - std::unordered_map>* keyUpHandlers = new std::unordered_map>(); + std::unordered_map>* keyUpHandlers = new std::unordered_map>(); int keyPressHandlerMaxId = 0; - std::unordered_map>* keyPressHandlers = new std::unordered_map>(); + std::unordered_map>* keyPressHandlers = new std::unordered_map>(); int changeHandlerMaxId = 0; - std::unordered_map>* changeHandlers = new std::unordered_map>(); + std::unordered_map>* changeHandlers = new std::unordered_map>(); int submitHandlerMaxId = 0; std::unordered_map>* submitHandlers = new std::unordered_map>(); int inputHandlerMaxId = 0; - std::unordered_map>* inputHandlers = new std::unordered_map>(); - - int loadHandlerMaxId = 0; - std::unordered_map>* loadHandlers = new std::unordered_map>(); - - int errorHandlerMaxId = 0; - std::unordered_map>* errorHandlers = new std::unordered_map>(); + std::unordered_map>* inputHandlers = new std::unordered_map>(); int resizeHandlerMaxId = 0; - std::unordered_map>* resizeHandlers = new std::unordered_map>(); + std::unordered_map>* resizeHandlers = new std::unordered_map>(); int scrollHandlerMaxId = 0; - std::unordered_map>* scrollHandlers = new std::unordered_map>(); + std::unordered_map>* scrollHandlers = new std::unordered_map>(); int contextMenuHandlerMaxId = 0; - std::unordered_map>* contextMenuHandlers = new std::unordered_map>(); + std::unordered_map>* contextMenuHandlers = new std::unordered_map>(); int dragStartHandlerMaxId = 0; - std::unordered_map>* dragStartHandlers = new std::unordered_map>(); + std::unordered_map>* dragStartHandlers = new std::unordered_map>(); int dragEndHandlerMaxId = 0; - std::unordered_map>* dragEndHandlers = new std::unordered_map>(); + std::unordered_map>* dragEndHandlers = new std::unordered_map>(); int dropHandlerMaxId = 0; - std::unordered_map>* dropHandlers = new std::unordered_map>(); - + std::unordered_map>* dropHandlers = new std::unordered_map>(); + + int wheelHandlerMaxId = 0; + std::unordered_map>* wheelHandlers = new std::unordered_map>(); + + int dragOverHandlerMaxId = 0; + std::unordered_map>* dragOverHandlers = new std::unordered_map>(); + + int dragEnterHandlerMaxId = 0; + std::unordered_map>* dragEnterHandlers = new std::unordered_map>(); + + int dragLeaveHandlerMaxId = 0; + std::unordered_map>* dragLeaveHandlers = new std::unordered_map>(); + __attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr); __attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::size_t idLenght); void* GetElementById(const std::string_view id) { @@ -105,6 +118,12 @@ export namespace Crafter::CppDOM::Bindings { __attribute__((import_module("env"), import_name("addMouseMoveListener"))) void AddMouseMoveListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeMouseMoveListener"))) void RemoveMouseMoveListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("addMouseDownListener"))) void AddMouseDownListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseDownListener"))) void RemoveMouseDownListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseUpListener"))) void AddMouseUpListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseUpListener"))) void RemoveMouseUpListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("addFocusListener"))) void AddFocusListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeFocusListener"))) void RemoveFocusListener(void* ptr, int id); @@ -129,12 +148,6 @@ export namespace Crafter::CppDOM::Bindings { __attribute__((import_module("env"), import_name("addInputListener"))) void AddInputListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeInputListener"))) void RemoveInputListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("addLoadListener"))) void AddLoadListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeLoadListener"))) void RemoveLoadListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addErrorListener"))) void AddErrorListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeErrorListener"))) void RemoveErrorListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("addResizeListener"))) void AddResizeListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeResizeListener"))) void RemoveResizeListener(void* ptr, int id); @@ -152,86 +165,217 @@ export namespace Crafter::CppDOM::Bindings { __attribute__((import_module("env"), import_name("addDropListener"))) void AddDropListener(void* ptr, int id); __attribute__((import_module("env"), import_name("removeDropListener"))) void RemoveDropListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addWheelListener"))) void AddWheelListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeWheelListener"))) void RemoveWheelListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragOverListener"))) void AddDragOverListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragOverListener"))) void RemoveDragOverListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragEnterListener"))) void AddDragEnterListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragEnterListener"))) void RemoveDragEnterListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragLeaveListener"))) void AddDragLeaveListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragLeaveListener"))) void RemoveDragLeaveListener(void* ptr, int id); } extern "C" { - __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(int a) { - Crafter::CppDOM::Bindings::clickHandlers->find(static_cast(a))->second(); + __attribute__((export_name("WasmAlloc"))) void* WasmAlloc(std::int32_t size) { + std::cout << std::format("Alloc: {}", size) << std::endl; + return std::malloc(size); + } + + __attribute__((export_name("WasmFree"))) void WasmFree(void* ptr) { + std::free(ptr); + } + + __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::clickHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteMouseOverHandler"))) void ExecuteMouseOverHandler(int a) { - Crafter::CppDOM::Bindings::mouseOverHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteMouseOverHandler"))) void ExecuteMouseOverHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseOverHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteMouseOutHandler"))) void ExecuteMouseOutHandler(int a) { - Crafter::CppDOM::Bindings::mouseOutHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteMouseOutHandler"))) void ExecuteMouseOutHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseOutHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteMouseMoveHandler"))) void ExecuteMouseMoveHandler(int a) { - Crafter::CppDOM::Bindings::mouseMoveHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteMouseMoveHandler"))) void ExecuteMouseMoveHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseMoveHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteFocusHandler"))) void ExecuteFocusHandler(int a) { - Crafter::CppDOM::Bindings::focusHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteMouseDownHandler"))) void ExecuteMouseDownHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseDownHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteBlurHandler"))) void ExecuteBlurHandler(int a) { - Crafter::CppDOM::Bindings::blurHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteMouseUpHandler"))) void ExecuteMouseUpHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseUpHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteKeyDownHandler"))) void ExecuteKeyDownHandler(int a, const char* key, const char* code, int keyCode) { - Crafter::CppDOM::Bindings::keyDownHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteFocusHandler"))) void ExecuteFocusHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::focusHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteKeyUpHandler"))) void ExecuteKeyUpHandler(int a, const char* key, const char* code, int keyCode) { - Crafter::CppDOM::Bindings::keyUpHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteBlurHandler"))) void ExecuteBlurHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::blurHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteKeyPressHandler"))) void ExecuteKeyPressHandler(int a, const char* key, const char* code, int keyCode) { - Crafter::CppDOM::Bindings::keyPressHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteKeyDownHandler"))) void ExecuteKeyDownHandler(std::int32_t handlerID, const char* key, std::int32_t keyCode, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::CppDOMBindings::keyDownHandlers->find(handlerID)->second(Crafter::KeyboardEvent(key, keyCode, altKey, ctrlKey, shiftKey, metaKey)); } - __attribute__((export_name("ExecuteChangeHandler"))) void ExecuteChangeHandler(int a) { - Crafter::CppDOM::Bindings::changeHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteKeyUpHandler"))) void ExecuteKeyUpHandler(std::int32_t handlerID, const char* key, std::int32_t keyCode, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::CppDOMBindings::keyUpHandlers->find(handlerID)->second(Crafter::KeyboardEvent(key, keyCode, altKey, ctrlKey, shiftKey, metaKey)); } - __attribute__((export_name("ExecuteSubmitHandler"))) void ExecuteSubmitHandler(int a) { - Crafter::CppDOM::Bindings::submitHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteKeyPressHandler"))) void ExecuteKeyPressHandler(std::int32_t handlerID, const char* key, std::int32_t keyCode, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::CppDOMBindings::keyPressHandlers->find(handlerID)->second(Crafter::KeyboardEvent(key, keyCode, altKey, ctrlKey, shiftKey, metaKey)); } - __attribute__((export_name("ExecuteInputHandler"))) void ExecuteInputHandler(int a) { - Crafter::CppDOM::Bindings::inputHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteChangeHandler"))) void ExecuteChangeHandler(std::int32_t handlerID, const char* value) { + Crafter::ChangeEvent event; + event.value = value; + Crafter::CppDOMBindings::changeHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteLoadHandler"))) void ExecuteLoadHandler(int a) { - Crafter::CppDOM::Bindings::loadHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteSubmitHandler"))) void ExecuteSubmitHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::submitHandlers->find(handlerID)->second(); } - __attribute__((export_name("ExecuteErrorHandler"))) void ExecuteErrorHandler(int a) { - Crafter::CppDOM::Bindings::errorHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteInputHandler"))) void ExecuteInputHandler(std::int32_t handlerID, const char* data, bool isComposing) { + Crafter::InputEvent event; + event.data = data; + event.isComposing = isComposing; + Crafter::CppDOMBindings::inputHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteResizeHandler"))) void ExecuteResizeHandler(int a) { - Crafter::CppDOM::Bindings::resizeHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteResizeHandler"))) void ExecuteResizeHandler(std::int32_t handlerID, unsigned int width, unsigned int height) { + Crafter::ResizeEvent event; + event.width = width; + event.height = height; + Crafter::CppDOMBindings::resizeHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteScrollHandler"))) void ExecuteScrollHandler(int a) { - Crafter::CppDOM::Bindings::scrollHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteScrollHandler"))) void ExecuteScrollHandler(std::int32_t handlerID, double scrollX, double scrollY) { + Crafter::ScrollEvent event; + event.scrollX = scrollX; + event.scrollY = scrollY; + Crafter::CppDOMBindings::scrollHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteContextMenuHandler"))) void ExecuteContextMenuHandler(int a) { - Crafter::CppDOM::Bindings::contextMenuHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteContextMenuHandler"))) void ExecuteContextMenuHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::contextMenuHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteDragStartHandler"))) void ExecuteDragStartHandler(int a) { - Crafter::CppDOM::Bindings::dragStartHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteDragStartHandler"))) void ExecuteDragStartHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dragStartHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteDragEndHandler"))) void ExecuteDragEndHandler(int a) { - Crafter::CppDOM::Bindings::dragEndHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteDragEndHandler"))) void ExecuteDragEndHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dragEndHandlers->find(handlerID)->second(event); } - __attribute__((export_name("ExecuteDropHandler"))) void ExecuteDropHandler(int a) { - Crafter::CppDOM::Bindings::dropHandlers->find(static_cast(a))->second(); + __attribute__((export_name("ExecuteDropHandler"))) void ExecuteDropHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dropHandlers->find(handlerID)->second(event); + } + + __attribute__((export_name("ExecuteWheelHandler"))) void ExecuteWheelHandler(std::int32_t handlerID, double deltaX, double deltaY, double deltaZ, int deltaMode, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::WheelEvent event; + event.deltaX = deltaX; + event.deltaY = deltaY; + event.deltaZ = deltaZ; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::wheelHandlers->find(handlerID)->second(event); + } + + __attribute__((export_name("ExecuteDragOverHandler"))) void ExecuteDragOverHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dragOverHandlers->find(handlerID)->second(event); + } + + __attribute__((export_name("ExecuteDragEnterHandler"))) void ExecuteDragEnterHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dragEnterHandlers->find(handlerID)->second(event); + } + + __attribute__((export_name("ExecuteDragLeaveHandler"))) void ExecuteDragLeaveHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::MouseEvent event; + event.clientX = clientX; + event.clientY = clientY; + event.screenX = screenX; + event.screenY = screenY; + event.button = button; + event.altKey = altKey; + event.ctrlKey = ctrlKey; + event.shiftKey = shiftKey; + event.metaKey = metaKey; + Crafter::CppDOMBindings::dragLeaveHandlers->find(handlerID)->second(event); } } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-EventTypes.cppm b/interfaces/Crafter.CppDOM-EventTypes.cppm new file mode 100644 index 0000000..745138b --- /dev/null +++ b/interfaces/Crafter.CppDOM-EventTypes.cppm @@ -0,0 +1,73 @@ +/* +Crafter.CppDOM +Copyright (C) 2025 Catcrafts +Catcrafts.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +export module Crafter.CppDOM:EventTypes; +import std; + +export namespace Crafter { + struct KeyboardEvent { + std::string key; + std::uint_fast8_t keyCode; + bool altKey; + bool ctrlKey; + bool shiftKey; + bool metaKey; + KeyboardEvent(const char* key, std::int32_t keyCode, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) : key(key), keyCode(keyCode), altKey(altKey), ctrlKey(ctrlKey), shiftKey(shiftKey), metaKey(metaKey) {} + }; + + // Mouse event structure + struct MouseEvent { + double clientX; + double clientY; + double screenX; + double screenY; + std::uint_fast32_t button; + std::uint_fast32_t buttons; + bool altKey; + bool ctrlKey; + bool shiftKey; + bool metaKey; + }; + + struct InputEvent { + std::string data; + bool isComposing; + }; + + struct WheelEvent : public MouseEvent { + double deltaX; + double deltaY; + double deltaZ; + }; + + struct ResizeEvent { + std::uint_fast32_t width; + std::uint_fast32_t height; + }; + + struct ScrollEvent { + double scrollX; + double scrollY; + }; + + struct ChangeEvent { + std::string value; + }; +} \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-HtmlElement.cppm b/interfaces/Crafter.CppDOM-HtmlElement.cppm index d79185f..6364e4c 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -21,311 +21,375 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.CppDOM:HtmlElement; import std; import :Bindings; +import :EventTypes; namespace Crafter { export class HtmlElement { public: void* const ptr; - std::vector handlers; - HtmlElement(const std::string_view id): ptr(CppDOM::Bindings::GetElementById(id)) { + std::vector handlers; + HtmlElement(const std::string_view id): ptr(CppDOMBindings::GetElementById(id)) { } - HtmlElement(const std::string_view id, const std::string_view html): ptr(CppDOM::Bindings::GetElementById(id)) { - CppDOM::Bindings::SetInnerHTML(ptr, html); + HtmlElement(const std::string_view id, const std::string_view html): ptr(CppDOMBindings::GetElementById(id)) { + CppDOMBindings::SetInnerHTML(ptr, html); } - void SetInnerHTML(const std::string_view& html) { - CppDOM::Bindings::SetInnerHTML(ptr, html); + void SetInnerHTML(const std::string_view html) { + CppDOMBindings::SetInnerHTML(ptr, html); } - // Event handling methods - int AddClickListener(std::function callback) { - int id = CppDOM::Bindings::clickHandlerMaxId++; + // Event handling methods with event data + + // Mouse Events + std::int32_t AddClickListener(std::function callback) { + std::int32_t id = CppDOMBindings::clickHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::clickHandlers->insert({id, callback}); - CppDOM::Bindings::AddClickListener(ptr, id); + CppDOMBindings::clickHandlers->insert({id, callback}); + CppDOMBindings::AddClickListener(ptr, id); return id; } - void RemoveClickListener(int id) { + void RemoveClickListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::clickHandlers->erase(id); - CppDOM::Bindings::RemoveClickListener(ptr, id); + CppDOMBindings::clickHandlers->erase(id); + CppDOMBindings::RemoveClickListener(ptr, id); } - int AddMouseOverListener(std::function callback) { - int id = CppDOM::Bindings::mouseOverHandlerMaxId++; + std::int32_t AddMouseOverListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseOverHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::mouseOverHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseOverListener(ptr, id); + CppDOMBindings::mouseOverHandlers->insert({id, callback}); + CppDOMBindings::AddMouseOverListener(ptr, id); return id; } - void RemoveMouseOverListener(int id) { + void RemoveMouseOverListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseOverHandlers->erase(id); - CppDOM::Bindings::RemoveMouseOverListener(ptr, id); + CppDOMBindings::mouseOverHandlers->erase(id); + CppDOMBindings::RemoveMouseOverListener(ptr, id); } - int AddMouseOutListener(std::function callback) { - int id = CppDOM::Bindings::mouseOutHandlerMaxId++; + std::int32_t AddMouseOutListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseOutHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::mouseOutHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseOutListener(ptr, id); + CppDOMBindings::mouseOutHandlers->insert({id, callback}); + CppDOMBindings::AddMouseOutListener(ptr, id); return id; } - void RemoveMouseOutListener(int id) { + void RemoveMouseOutListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseOutHandlers->erase(id); - CppDOM::Bindings::RemoveMouseOutListener(ptr, id); + CppDOMBindings::mouseOutHandlers->erase(id); + CppDOMBindings::RemoveMouseOutListener(ptr, id); } - int AddMouseMoveListener(std::function callback) { - int id = CppDOM::Bindings::mouseMoveHandlerMaxId++; + std::int32_t AddMouseMoveListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseMoveHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::mouseMoveHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseMoveListener(ptr, id); + CppDOMBindings::mouseMoveHandlers->insert({id, callback}); + CppDOMBindings::AddMouseMoveListener(ptr, id); return id; } - void RemoveMouseMoveListener(int id) { + void RemoveMouseMoveListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseMoveHandlers->erase(id); - CppDOM::Bindings::RemoveMouseMoveListener(ptr, id); + CppDOMBindings::mouseMoveHandlers->erase(id); + CppDOMBindings::RemoveMouseMoveListener(ptr, id); } - int AddFocusListener(std::function callback) { - int id = CppDOM::Bindings::focusHandlerMaxId++; + std::int32_t AddMouseDownListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseDownHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::focusHandlers->insert({id, callback}); - CppDOM::Bindings::AddFocusListener(ptr, id); + CppDOMBindings::mouseDownHandlers->insert({id, callback}); + CppDOMBindings::AddMouseDownListener(ptr, id); return id; } - void RemoveFocusListener(int id) { + void RemoveMouseDownListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::focusHandlers->erase(id); - CppDOM::Bindings::RemoveFocusListener(ptr, id); + CppDOMBindings::mouseDownHandlers->erase(id); + CppDOMBindings::RemoveMouseDownListener(ptr, id); } - int AddBlurListener(std::function callback) { - int id = CppDOM::Bindings::blurHandlerMaxId++; + std::int32_t AddMouseUpListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseUpHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::blurHandlers->insert({id, callback}); - CppDOM::Bindings::AddBlurListener(ptr, id); + CppDOMBindings::mouseUpHandlers->insert({id, callback}); + CppDOMBindings::AddMouseUpListener(ptr, id); return id; } - void RemoveBlurListener(int id) { + void RemoveMouseUpListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::blurHandlers->erase(id); - CppDOM::Bindings::RemoveBlurListener(ptr, id); + CppDOMBindings::mouseUpHandlers->erase(id); + CppDOMBindings::RemoveMouseUpListener(ptr, id); } - int AddKeyDownListener(std::function callback) { - int id = CppDOM::Bindings::keyDownHandlerMaxId++; + // Focus Events + std::int32_t AddFocusListener(std::function callback) { + std::int32_t id = CppDOMBindings::focusHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::keyDownHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyDownListener(ptr, id); + CppDOMBindings::focusHandlers->insert({id, callback}); + CppDOMBindings::AddFocusListener(ptr, id); return id; } - void RemoveKeyDownListener(int id) { + void RemoveFocusListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyDownHandlers->erase(id); - CppDOM::Bindings::RemoveKeyDownListener(ptr, id); + CppDOMBindings::focusHandlers->erase(id); + CppDOMBindings::RemoveFocusListener(ptr, id); } - int AddKeyUpListener(std::function callback) { - int id = CppDOM::Bindings::keyUpHandlerMaxId++; + std::int32_t AddBlurListener(std::function callback) { + std::int32_t id = CppDOMBindings::blurHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::keyUpHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyUpListener(ptr, id); + CppDOMBindings::blurHandlers->insert({id, callback}); + CppDOMBindings::AddBlurListener(ptr, id); return id; } - void RemoveKeyUpListener(int id) { + void RemoveBlurListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyUpHandlers->erase(id); - CppDOM::Bindings::RemoveKeyUpListener(ptr, id); + CppDOMBindings::blurHandlers->erase(id); + CppDOMBindings::RemoveBlurListener(ptr, id); } - int AddKeyPressListener(std::function callback) { - int id = CppDOM::Bindings::keyPressHandlerMaxId++; + // Keyboard Events + std::int32_t AddKeyDownListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyDownHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::keyPressHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyPressListener(ptr, id); + CppDOMBindings::keyDownHandlers->insert({id, callback}); + CppDOMBindings::AddKeyDownListener(ptr, id); return id; } - void RemoveKeyPressListener(int id) { + void RemoveKeyDownListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyPressHandlers->erase(id); - CppDOM::Bindings::RemoveKeyPressListener(ptr, id); + CppDOMBindings::keyDownHandlers->erase(id); + CppDOMBindings::RemoveKeyDownListener(ptr, id); } - int AddChangeListener(std::function callback) { - int id = CppDOM::Bindings::changeHandlerMaxId++; + std::int32_t AddKeyUpListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyUpHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::changeHandlers->insert({id, callback}); - CppDOM::Bindings::AddChangeListener(ptr, id); + CppDOMBindings::keyUpHandlers->insert({id, callback}); + CppDOMBindings::AddKeyUpListener(ptr, id); return id; } - void RemoveChangeListener(int id) { + void RemoveKeyUpListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::changeHandlers->erase(id); - CppDOM::Bindings::RemoveChangeListener(ptr, id); + CppDOMBindings::keyUpHandlers->erase(id); + CppDOMBindings::RemoveKeyUpListener(ptr, id); } - int AddSubmitListener(std::function callback) { - int id = CppDOM::Bindings::submitHandlerMaxId++; + std::int32_t AddKeyPressListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyPressHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::submitHandlers->insert({id, callback}); - CppDOM::Bindings::AddSubmitListener(ptr, id); + CppDOMBindings::keyPressHandlers->insert({id, callback}); + CppDOMBindings::AddKeyPressListener(ptr, id); return id; } - void RemoveSubmitListener(int id) { + void RemoveKeyPressListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::submitHandlers->erase(id); - CppDOM::Bindings::RemoveSubmitListener(ptr, id); + CppDOMBindings::keyPressHandlers->erase(id); + CppDOMBindings::RemoveKeyPressListener(ptr, id); } - int AddInputListener(std::function callback) { - int id = CppDOM::Bindings::inputHandlerMaxId++; + // Form Events + std::int32_t AddChangeListener(std::function callback) { + std::int32_t id = CppDOMBindings::changeHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::inputHandlers->insert({id, callback}); - CppDOM::Bindings::AddInputListener(ptr, id); + CppDOMBindings::changeHandlers->insert({id, callback}); + CppDOMBindings::AddChangeListener(ptr, id); return id; } - void RemoveInputListener(int id) { + void RemoveChangeListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::inputHandlers->erase(id); - CppDOM::Bindings::RemoveInputListener(ptr, id); + CppDOMBindings::changeHandlers->erase(id); + CppDOMBindings::RemoveChangeListener(ptr, id); } - int AddLoadListener(std::function callback) { - int id = CppDOM::Bindings::loadHandlerMaxId++; + std::int32_t AddSubmitListener(std::function callback) { + std::int32_t id = CppDOMBindings::submitHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::loadHandlers->insert({id, callback}); - CppDOM::Bindings::AddLoadListener(ptr, id); + CppDOMBindings::submitHandlers->insert({id, callback}); + CppDOMBindings::AddSubmitListener(ptr, id); return id; } - void RemoveLoadListener(int id) { + void RemoveSubmitListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::loadHandlers->erase(id); - CppDOM::Bindings::RemoveLoadListener(ptr, id); + CppDOMBindings::submitHandlers->erase(id); + CppDOMBindings::RemoveSubmitListener(ptr, id); } - int AddErrorListener(std::function callback) { - int id = CppDOM::Bindings::errorHandlerMaxId++; + std::int32_t AddInputListener(std::function callback) { + std::int32_t id = CppDOMBindings::inputHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::errorHandlers->insert({id, callback}); - CppDOM::Bindings::AddErrorListener(ptr, id); + CppDOMBindings::inputHandlers->insert({id, callback}); + CppDOMBindings::AddInputListener(ptr, id); return id; } - void RemoveErrorListener(int id) { + void RemoveInputListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::errorHandlers->erase(id); - CppDOM::Bindings::RemoveErrorListener(ptr, id); + CppDOMBindings::inputHandlers->erase(id); + CppDOMBindings::RemoveInputListener(ptr, id); } - int AddResizeListener(std::function callback) { - int id = CppDOM::Bindings::resizeHandlerMaxId++; + std::int32_t AddResizeListener(std::function callback) { + std::int32_t id = CppDOMBindings::resizeHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::resizeHandlers->insert({id, callback}); - CppDOM::Bindings::AddResizeListener(ptr, id); + CppDOMBindings::resizeHandlers->insert({id, callback}); + CppDOMBindings::AddResizeListener(ptr, id); return id; } - void RemoveResizeListener(int id) { + void RemoveResizeListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::resizeHandlers->erase(id); - CppDOM::Bindings::RemoveResizeListener(ptr, id); + CppDOMBindings::resizeHandlers->erase(id); + CppDOMBindings::RemoveResizeListener(ptr, id); } - int AddScrollListener(std::function callback) { - int id = CppDOM::Bindings::scrollHandlerMaxId++; + std::int32_t AddScrollListener(std::function callback) { + std::int32_t id = CppDOMBindings::scrollHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::scrollHandlers->insert({id, callback}); - CppDOM::Bindings::AddScrollListener(ptr, id); + CppDOMBindings::scrollHandlers->insert({id, callback}); + CppDOMBindings::AddScrollListener(ptr, id); return id; } - void RemoveScrollListener(int id) { + void RemoveScrollListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::scrollHandlers->erase(id); - CppDOM::Bindings::RemoveScrollListener(ptr, id); + CppDOMBindings::scrollHandlers->erase(id); + CppDOMBindings::RemoveScrollListener(ptr, id); } - int AddContextMenuListener(std::function callback) { - int id = CppDOM::Bindings::contextMenuHandlerMaxId++; + // Context Menu Events + std::int32_t AddContextMenuListener(std::function callback) { + std::int32_t id = CppDOMBindings::contextMenuHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::contextMenuHandlers->insert({id, callback}); - CppDOM::Bindings::AddContextMenuListener(ptr, id); + CppDOMBindings::contextMenuHandlers->insert({id, callback}); + CppDOMBindings::AddContextMenuListener(ptr, id); return id; } - void RemoveContextMenuListener(int id) { + void RemoveContextMenuListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::contextMenuHandlers->erase(id); - CppDOM::Bindings::RemoveContextMenuListener(ptr, id); + CppDOMBindings::contextMenuHandlers->erase(id); + CppDOMBindings::RemoveContextMenuListener(ptr, id); } - int AddDragStartListener(std::function callback) { - int id = CppDOM::Bindings::dragStartHandlerMaxId++; + // Drag and Drop Events + std::int32_t AddDragStartListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragStartHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::dragStartHandlers->insert({id, callback}); - CppDOM::Bindings::AddDragStartListener(ptr, id); + CppDOMBindings::dragStartHandlers->insert({id, callback}); + CppDOMBindings::AddDragStartListener(ptr, id); return id; } - void RemoveDragStartListener(int id) { + void RemoveDragStartListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dragStartHandlers->erase(id); - CppDOM::Bindings::RemoveDragStartListener(ptr, id); + CppDOMBindings::dragStartHandlers->erase(id); + CppDOMBindings::RemoveDragStartListener(ptr, id); } - int AddDragEndListener(std::function callback) { - int id = CppDOM::Bindings::dragEndHandlerMaxId++; + std::int32_t AddDragEndListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragEndHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::dragEndHandlers->insert({id, callback}); - CppDOM::Bindings::AddDragEndListener(ptr, id); + CppDOMBindings::dragEndHandlers->insert({id, callback}); + CppDOMBindings::AddDragEndListener(ptr, id); return id; } - void RemoveDragEndListener(int id) { + void RemoveDragEndListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dragEndHandlers->erase(id); - CppDOM::Bindings::RemoveDragEndListener(ptr, id); + CppDOMBindings::dragEndHandlers->erase(id); + CppDOMBindings::RemoveDragEndListener(ptr, id); } - int AddDropListener(std::function callback) { - int id = CppDOM::Bindings::dropHandlerMaxId++; + std::int32_t AddDropListener(std::function callback) { + std::int32_t id = CppDOMBindings::dropHandlerMaxId++; handlers.push_back(id); - CppDOM::Bindings::dropHandlers->insert({id, callback}); - CppDOM::Bindings::AddDropListener(ptr, id); + CppDOMBindings::dropHandlers->insert({id, callback}); + CppDOMBindings::AddDropListener(ptr, id); return id; } - void RemoveDropListener(int id) { + void RemoveDropListener(std::int32_t id) { handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dropHandlers->erase(id); - CppDOM::Bindings::RemoveDropListener(ptr, id); + CppDOMBindings::dropHandlers->erase(id); + CppDOMBindings::RemoveDropListener(ptr, id); + } + + // Additional Drag Events + std::int32_t AddDragOverListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragOverHandlerMaxId++; + handlers.push_back(id); + CppDOMBindings::dragOverHandlers->insert({id, callback}); + CppDOMBindings::AddDragOverListener(ptr, id); + return id; + } + + void RemoveDragOverListener(std::int32_t id) { + handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + CppDOMBindings::dragOverHandlers->erase(id); + CppDOMBindings::RemoveDragOverListener(ptr, id); + } + + std::int32_t AddDragEnterListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragEnterHandlerMaxId++; + handlers.push_back(id); + CppDOMBindings::dragEnterHandlers->insert({id, callback}); + CppDOMBindings::AddDragEnterListener(ptr, id); + return id; + } + + void RemoveDragEnterListener(std::int32_t id) { + handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + CppDOMBindings::dragEnterHandlers->erase(id); + CppDOMBindings::RemoveDragEnterListener(ptr, id); + } + + std::int32_t AddDragLeaveListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragLeaveHandlerMaxId++; + handlers.push_back(id); + CppDOMBindings::dragLeaveHandlers->insert({id, callback}); + CppDOMBindings::AddDragLeaveListener(ptr, id); + return id; + } + + void RemoveDragLeaveListener(std::int32_t id) { + handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + CppDOMBindings::dragLeaveHandlers->erase(id); + CppDOMBindings::RemoveDragLeaveListener(ptr, id); + } + + // Wheel Event + std::int32_t AddWheelListener(std::function callback) { + std::int32_t id = CppDOMBindings::wheelHandlerMaxId++; + handlers.push_back(id); + CppDOMBindings::wheelHandlers->insert({id, callback}); + CppDOMBindings::AddWheelListener(ptr, id); + return id; + } + + void RemoveWheelListener(std::int32_t id) { + handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + CppDOMBindings::wheelHandlers->erase(id); + CppDOMBindings::RemoveWheelListener(ptr, id); } ~HtmlElement(){ - for(int handler : handlers) { - // Clean up all handlers based on type - this is a simplified approach - // In practice, you'd want to track handler types to clean them properly - CppDOM::Bindings::clickHandlers->erase(handler); - CppDOM::Bindings::RemoveClickListener(ptr, handler); + for(std::int32_t handler : handlers) { + CppDOMBindings::clickHandlers->erase(handler); + CppDOMBindings::RemoveClickListener(ptr, handler); } - CppDOM::Bindings::FreeJs(ptr); + CppDOMBindings::FreeJs(ptr); } }; } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM.cppm b/interfaces/Crafter.CppDOM.cppm index b1f2e0b..d129ff2 100644 --- a/interfaces/Crafter.CppDOM.cppm +++ b/interfaces/Crafter.CppDOM.cppm @@ -20,4 +20,5 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.CppDOM; export import :Bindings; -export import :HtmlElement; \ No newline at end of file +export import :HtmlElement; +export import :EventTypes; \ No newline at end of file diff --git a/project.json b/project.json index 330c796..a56145a 100644 --- a/project.json +++ b/project.json @@ -3,7 +3,7 @@ "configurations": [ { "name": "lib", - "interfaces": ["interfaces/Crafter.CppDOM-HtmlElement", "interfaces/Crafter.CppDOM", "interfaces/Crafter.CppDOM-Bindings"], + "interfaces": ["interfaces/Crafter.CppDOM-HtmlElement", "interfaces/Crafter.CppDOM", "interfaces/Crafter.CppDOM-Bindings", "interfaces/Crafter.CppDOM-EventTypes"], "additional_files": ["additional/env.js"], "type":"library", "target":"wasm32-wasi" @@ -14,4 +14,4 @@ "debug": true } ] -} +} \ No newline at end of file From 2254ad53c5d63ead627b5ba2b49503ef33d5b970 Mon Sep 17 00:00:00 2001 From: Jorijn van der Graaf Date: Mon, 10 Nov 2025 20:25:50 +0100 Subject: [PATCH 2/2] fixes --- examples/CompleteEventHandling/README.md | 84 ------- examples/CompleteEventHandling/main.cpp | 75 ------ examples/CompleteEventHandling/project.json | 17 -- examples/CompleteEventHandling/run.sh | 1 - examples/EnhancedEventHandling/main.cpp | 42 ---- ...ppm => Crafter.CppDOM-BindingsExport.cppm} | 203 +--------------- interfaces/Crafter.CppDOM-BindingsImport.cppm | 108 +++++++++ interfaces/Crafter.CppDOM-EventTypes.cppm | 6 + interfaces/Crafter.CppDOM-HtmlElement.cppm | 223 +++++++++++++----- interfaces/Crafter.CppDOM.cppm | 5 +- project.json | 2 +- 11 files changed, 300 insertions(+), 466 deletions(-) delete mode 100644 examples/CompleteEventHandling/README.md delete mode 100644 examples/CompleteEventHandling/main.cpp delete mode 100644 examples/CompleteEventHandling/project.json delete mode 100755 examples/CompleteEventHandling/run.sh rename interfaces/{Crafter.CppDOM-Bindings.cppm => Crafter.CppDOM-BindingsExport.cppm} (54%) create mode 100644 interfaces/Crafter.CppDOM-BindingsImport.cppm diff --git a/examples/CompleteEventHandling/README.md b/examples/CompleteEventHandling/README.md deleted file mode 100644 index 175741a..0000000 --- a/examples/CompleteEventHandling/README.md +++ /dev/null @@ -1,84 +0,0 @@ -# Complete Event Handling Example - -This example demonstrates comprehensive event handling capabilities in Crafter.CppDOM. - -## Features - -- Shows how to handle various types of DOM events using C++ -- Demonstrates mouse, keyboard, form, and window events -- Illustrates proper event listener attachment and callback handling -- Shows real-time interaction with UI elements - -## Event Types Demonstrated - -### Mouse Events -- Click events -- Mouse over/out events -- Mouse move events - -### Focus Events -- Focus and blur events - -### Keyboard Events -- Key down, up, and press events - -### Form Events -- Change, submit, and input events - -### Window Events -- Load, error, resize, and scroll events - -### Context Menu Events -- Context menu events - -### Drag and Drop Events -- Drag start, end, and drop events - -## Usage - -```cpp -import Crafter.CppDOM; -using namespace Crafter::CppDOM; - -int main(){ - // Create UI elements - HtmlElement body("body"); - body.SetInnerHTML("

Complete Event Handling Demo

" - "" - "" - "

Events will appear here

"); - - // Handle click event - HtmlElement button("myButton"); - button.AddClickListener([]() { - HtmlElement output("output"); - output.SetInnerHTML("Button was clicked!"); - }); - - // Handle keyboard events - HtmlElement input("textInput"); - input.AddInputListener([]() { - HtmlElement output("output"); - output.SetInnerHTML("Input changed!"); - }); - - // Handle form events - input.AddChangeListener([]() { - HtmlElement output("output"); - output.SetInnerHTML("Form value changed!"); - }); - - return 0; -} -``` - -## Building and Running - -```bash -crafter-build build executable -run.sh -``` - -Then navigate to `http://localhost:8080/` in your browser. - -If caddy is not installed, you can use your favorite static file server instead. \ No newline at end of file diff --git a/examples/CompleteEventHandling/main.cpp b/examples/CompleteEventHandling/main.cpp deleted file mode 100644 index 396477d..0000000 --- a/examples/CompleteEventHandling/main.cpp +++ /dev/null @@ -1,75 +0,0 @@ -import Crafter.CppDOM; -using namespace Crafter; - -HtmlElement* body = new HtmlElement("body", "
"); -HtmlElement* button = new HtmlElement("myButton"); -HtmlElement* input = new HtmlElement("textInput"); -HtmlElement* output = new HtmlElement("output"); - -int main(){ - // Click event - button->AddClickListener([&]() { - output->SetInnerHTML("Button was clicked!"); - }); - - // Mouse events - button->AddMouseOverListener([&]() { - output->SetInnerHTML("Mouse over button!"); - }); - - button->AddMouseOutListener([&]() { - output->SetInnerHTML("Mouse left button!"); - }); - - // Focus/Blur events - input->AddFocusListener([&]() { - output->SetInnerHTML("Input focused!"); - }); - - input->AddBlurListener([&]() { - output->SetInnerHTML("Input blurred!"); - }); - - // Keyboard events - input->AddKeyDownListener([&]() { - output->SetInnerHTML("Key pressed in input!"); - }); - - input->AddKeyUpListener([&]() { - output->SetInnerHTML("Key released in input!"); - }); - - // Input/change events - input->AddInputListener([&]() { - output->SetInnerHTML("Input value changed!"); - }); - - input->AddChangeListener([&]() { - output->SetInnerHTML("Input value changed and lost focus!"); - }); - - // Context menu - button->AddContextMenuListener([&]() { - output->SetInnerHTML("Context menu opened!"); - }); - - // Scroll event on body - body->AddScrollListener([&]() { - output->SetInnerHTML("Page scrolled!"); - }); - - // Resize event - body->AddResizeListener([&]() { - output->SetInnerHTML("Window resized!"); - }); - - // Load event - body->AddLoadListener([&]() { - output->SetInnerHTML("Page loaded!"); - }); - - // Error event - body->AddErrorListener([&]() { - output->SetInnerHTML("An error occurred!"); - }); -} \ No newline at end of file diff --git a/examples/CompleteEventHandling/project.json b/examples/CompleteEventHandling/project.json deleted file mode 100644 index 9750e20..0000000 --- a/examples/CompleteEventHandling/project.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "main", - "configurations": [ - { - "name": "executable", - "implementations": ["main"], - "target": "wasm32-wasi", - "debug" : true, - "dependencies": [ - { - "path":"../../project.json", - "configuration":"lib-debug" - } - ] - } - ] -} \ No newline at end of file diff --git a/examples/CompleteEventHandling/run.sh b/examples/CompleteEventHandling/run.sh deleted file mode 100755 index e706621..0000000 --- a/examples/CompleteEventHandling/run.sh +++ /dev/null @@ -1 +0,0 @@ -caddy file-server --listen :8080 --root bin/executable \ No newline at end of file diff --git a/examples/EnhancedEventHandling/main.cpp b/examples/EnhancedEventHandling/main.cpp index 8d7d864..fb89730 100644 --- a/examples/EnhancedEventHandling/main.cpp +++ b/examples/EnhancedEventHandling/main.cpp @@ -4,30 +4,13 @@ import std; HtmlElement* body = new HtmlElement("body", "
" "

Enhanced Event Handling Demo

" - "" - "" "" - "" "
" "
"); -HtmlElement* clickButton = new HtmlElement("clickButton"); -HtmlElement* mouseButton = new HtmlElement("mouseButton"); HtmlElement* keyInput = new HtmlElement("keyInput"); -HtmlElement* changeInput = new HtmlElement("changeInput"); HtmlElement* output = new HtmlElement("output"); int main(){ - // Click event - simple handler - clickButton->AddClickListener([&]() { - output->SetInnerHTML("

Simple click event triggered!

"); - }); - - // Mouse events with position data - // mouseButton->AddMouseMoveListener([&](MouseEvent event) { - // output->SetInnerHTML("

Mouse moved to: (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")

"); - // }); - - // Keyboard events with rich data keyInput->AddKeyDownListener([&](KeyboardEvent event) { std::string keyInfo = std::format("

Key pressed: {}

", event.key); if (event.ctrlKey) keyInfo += "

Ctrl key pressed

"; @@ -35,29 +18,4 @@ int main(){ if (event.altKey) keyInfo += "

Alt key pressed

"; output->SetInnerHTML(keyInfo); }); - - // // Input event with data - // keyInput->AddInputListener([&](InputEvent event) { - // output->SetInnerHTML(std::format("

Input data: {} (composing: {})

", event.data, event.isComposing)); - // }); - - // Change event with value - changeInput->AddChangeListener([&](ChangeEvent event) { - output->SetInnerHTML("

Input value changed to: '" + event.value + "'

"); - }); - - // Context menu with position - mouseButton->AddContextMenuListener([&](MouseEvent event) { - output->SetInnerHTML("

Context menu at: (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")

"); - }); - - // Resize event - body->AddResizeListener([&](ResizeEvent event) { - output->SetInnerHTML("

Window resized to: " + std::to_string(event.width) + "x" + std::to_string(event.height) + "

"); - }); - - // Scroll event - body->AddScrollListener([&](ScrollEvent event) { - output->SetInnerHTML("

Scrolled to: (" + std::to_string(event.scrollX) + ", " + std::to_string(event.scrollY) + ")

"); - }); } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-Bindings.cppm b/interfaces/Crafter.CppDOM-BindingsExport.cppm similarity index 54% rename from interfaces/Crafter.CppDOM-Bindings.cppm rename to interfaces/Crafter.CppDOM-BindingsExport.cppm index 3c76173..7ebe266 100644 --- a/interfaces/Crafter.CppDOM-Bindings.cppm +++ b/interfaces/Crafter.CppDOM-BindingsExport.cppm @@ -18,7 +18,7 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -export module Crafter.CppDOM:Bindings; +export module Crafter.CppDOM:BindingsExport; import std; import :EventTypes; @@ -94,89 +94,6 @@ export namespace Crafter::CppDOMBindings { int dragLeaveHandlerMaxId = 0; std::unordered_map>* dragLeaveHandlers = new std::unordered_map>(); - - __attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr); - __attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::size_t idLenght); - void* GetElementById(const std::string_view id) { - return GetElementById(id.data(), id.size()); - } - __attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(void* ptr, const char* html, std::size_t htmlLenght); - void SetInnerHTML(void* ptr, const std::string_view html) { - SetInnerHTML(ptr, html.data(), html.size()); - } - - // Event handling functions - __attribute__((import_module("env"), import_name("addClickListener"))) void AddClickListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeClickListener"))) void RemoveClickListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addMouseOverListener"))) void AddMouseOverListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeMouseOverListener"))) void RemoveMouseOverListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addMouseOutListener"))) void AddMouseOutListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeMouseOutListener"))) void RemoveMouseOutListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addMouseMoveListener"))) void AddMouseMoveListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeMouseMoveListener"))) void RemoveMouseMoveListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addMouseDownListener"))) void AddMouseDownListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeMouseDownListener"))) void RemoveMouseDownListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addMouseUpListener"))) void AddMouseUpListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeMouseUpListener"))) void RemoveMouseUpListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addFocusListener"))) void AddFocusListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeFocusListener"))) void RemoveFocusListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addBlurListener"))) void AddBlurListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeBlurListener"))) void RemoveBlurListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addKeyDownListener"))) void AddKeyDownListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeKeyDownListener"))) void RemoveKeyDownListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addKeyUpListener"))) void AddKeyUpListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeKeyUpListener"))) void RemoveKeyUpListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addKeyPressListener"))) void AddKeyPressListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeKeyPressListener"))) void RemoveKeyPressListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addChangeListener"))) void AddChangeListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeChangeListener"))) void RemoveChangeListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addSubmitListener"))) void AddSubmitListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeSubmitListener"))) void RemoveSubmitListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addInputListener"))) void AddInputListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeInputListener"))) void RemoveInputListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addResizeListener"))) void AddResizeListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeResizeListener"))) void RemoveResizeListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addScrollListener"))) void AddScrollListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeScrollListener"))) void RemoveScrollListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addContextMenuListener"))) void AddContextMenuListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeContextMenuListener"))) void RemoveContextMenuListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDragStartListener"))) void AddDragStartListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDragStartListener"))) void RemoveDragStartListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDragEndListener"))) void AddDragEndListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDragEndListener"))) void RemoveDragEndListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDropListener"))) void AddDropListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDropListener"))) void RemoveDropListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addWheelListener"))) void AddWheelListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeWheelListener"))) void RemoveWheelListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDragOverListener"))) void AddDragOverListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDragOverListener"))) void RemoveDragOverListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDragEnterListener"))) void AddDragEnterListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDragEnterListener"))) void RemoveDragEnterListener(void* ptr, int id); - - __attribute__((import_module("env"), import_name("addDragLeaveListener"))) void AddDragLeaveListener(void* ptr, int id); - __attribute__((import_module("env"), import_name("removeDragLeaveListener"))) void RemoveDragLeaveListener(void* ptr, int id); } extern "C" { @@ -234,9 +151,7 @@ extern "C" { } __attribute__((export_name("ExecuteChangeHandler"))) void ExecuteChangeHandler(std::int32_t handlerID, const char* value) { - Crafter::ChangeEvent event; - event.value = value; - Crafter::CppDOMBindings::changeHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::changeHandlers->find(handlerID)->second(Crafter::ChangeEvent(value)); } __attribute__((export_name("ExecuteSubmitHandler"))) void ExecuteSubmitHandler(std::int32_t handlerID) { @@ -244,138 +159,46 @@ extern "C" { } __attribute__((export_name("ExecuteInputHandler"))) void ExecuteInputHandler(std::int32_t handlerID, const char* data, bool isComposing) { - Crafter::InputEvent event; - event.data = data; - event.isComposing = isComposing; - Crafter::CppDOMBindings::inputHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::inputHandlers->find(handlerID)->second(Crafter::InputEvent(data, isComposing)); } __attribute__((export_name("ExecuteResizeHandler"))) void ExecuteResizeHandler(std::int32_t handlerID, unsigned int width, unsigned int height) { - Crafter::ResizeEvent event; - event.width = width; - event.height = height; - Crafter::CppDOMBindings::resizeHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::resizeHandlers->find(handlerID)->second(Crafter::ResizeEvent(width, height)); } __attribute__((export_name("ExecuteScrollHandler"))) void ExecuteScrollHandler(std::int32_t handlerID, double scrollX, double scrollY) { - Crafter::ScrollEvent event; - event.scrollX = scrollX; - event.scrollY = scrollY; - Crafter::CppDOMBindings::scrollHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::scrollHandlers->find(handlerID)->second(Crafter::ScrollEvent(scrollX, scrollY)); } __attribute__((export_name("ExecuteContextMenuHandler"))) void ExecuteContextMenuHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::contextMenuHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::contextMenuHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteDragStartHandler"))) void ExecuteDragStartHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dragStartHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dragStartHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteDragEndHandler"))) void ExecuteDragEndHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dragEndHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dragEndHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteDropHandler"))) void ExecuteDropHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dropHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dropHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteWheelHandler"))) void ExecuteWheelHandler(std::int32_t handlerID, double deltaX, double deltaY, double deltaZ, int deltaMode, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::WheelEvent event; - event.deltaX = deltaX; - event.deltaY = deltaY; - event.deltaZ = deltaZ; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::wheelHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::wheelHandlers->find(handlerID)->second(Crafter::WheelEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey, deltaX, deltaY, deltaZ)); } __attribute__((export_name("ExecuteDragOverHandler"))) void ExecuteDragOverHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dragOverHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dragOverHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteDragEnterHandler"))) void ExecuteDragEnterHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dragEnterHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dragEnterHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteDragLeaveHandler"))) void ExecuteDragLeaveHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, int button, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { - Crafter::MouseEvent event; - event.clientX = clientX; - event.clientY = clientY; - event.screenX = screenX; - event.screenY = screenY; - event.button = button; - event.altKey = altKey; - event.ctrlKey = ctrlKey; - event.shiftKey = shiftKey; - event.metaKey = metaKey; - Crafter::CppDOMBindings::dragLeaveHandlers->find(handlerID)->second(event); + Crafter::CppDOMBindings::dragLeaveHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, 0, altKey, ctrlKey, shiftKey, metaKey)); } } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-BindingsImport.cppm b/interfaces/Crafter.CppDOM-BindingsImport.cppm new file mode 100644 index 0000000..32ea9ec --- /dev/null +++ b/interfaces/Crafter.CppDOM-BindingsImport.cppm @@ -0,0 +1,108 @@ +/* +Crafter.CppDOM +Copyright (C) 2025 Catcrafts +Catcrafts.net + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3.0 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +export module Crafter.CppDOM:BindingsImport; +import std; +import :EventTypes; + +export namespace Crafter::CppDOMBindings { + __attribute__((import_module("env"), import_name("freeJs"))) void FreeJs(void* ptr); + __attribute__((import_module("env"), import_name("getElementById"))) void* GetElementById(const char* id, std::size_t idLenght); + void* GetElementById(const std::string_view id) { + return GetElementById(id.data(), id.size()); + } + __attribute__((import_module("env"), import_name("setInnerHTML"))) void SetInnerHTML(void* ptr, const char* html, std::size_t htmlLenght); + void SetInnerHTML(void* ptr, const std::string_view html) { + SetInnerHTML(ptr, html.data(), html.size()); + } + + // Event handling functions + __attribute__((import_module("env"), import_name("addClickListener"))) void AddClickListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeClickListener"))) void RemoveClickListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseOverListener"))) void AddMouseOverListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseOverListener"))) void RemoveMouseOverListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseOutListener"))) void AddMouseOutListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseOutListener"))) void RemoveMouseOutListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseMoveListener"))) void AddMouseMoveListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseMoveListener"))) void RemoveMouseMoveListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseDownListener"))) void AddMouseDownListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseDownListener"))) void RemoveMouseDownListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addMouseUpListener"))) void AddMouseUpListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeMouseUpListener"))) void RemoveMouseUpListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addFocusListener"))) void AddFocusListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeFocusListener"))) void RemoveFocusListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addBlurListener"))) void AddBlurListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeBlurListener"))) void RemoveBlurListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addKeyDownListener"))) void AddKeyDownListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeKeyDownListener"))) void RemoveKeyDownListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addKeyUpListener"))) void AddKeyUpListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeKeyUpListener"))) void RemoveKeyUpListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addKeyPressListener"))) void AddKeyPressListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeKeyPressListener"))) void RemoveKeyPressListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addChangeListener"))) void AddChangeListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeChangeListener"))) void RemoveChangeListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addSubmitListener"))) void AddSubmitListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeSubmitListener"))) void RemoveSubmitListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addInputListener"))) void AddInputListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeInputListener"))) void RemoveInputListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addResizeListener"))) void AddResizeListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeResizeListener"))) void RemoveResizeListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addScrollListener"))) void AddScrollListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeScrollListener"))) void RemoveScrollListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addContextMenuListener"))) void AddContextMenuListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeContextMenuListener"))) void RemoveContextMenuListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragStartListener"))) void AddDragStartListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragStartListener"))) void RemoveDragStartListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragEndListener"))) void AddDragEndListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragEndListener"))) void RemoveDragEndListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDropListener"))) void AddDropListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDropListener"))) void RemoveDropListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addWheelListener"))) void AddWheelListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeWheelListener"))) void RemoveWheelListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragOverListener"))) void AddDragOverListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragOverListener"))) void RemoveDragOverListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragEnterListener"))) void AddDragEnterListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragEnterListener"))) void RemoveDragEnterListener(void* ptr, int id); + + __attribute__((import_module("env"), import_name("addDragLeaveListener"))) void AddDragLeaveListener(void* ptr, int id); + __attribute__((import_module("env"), import_name("removeDragLeaveListener"))) void RemoveDragLeaveListener(void* ptr, int id); +} \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-EventTypes.cppm b/interfaces/Crafter.CppDOM-EventTypes.cppm index 745138b..ad92c2f 100644 --- a/interfaces/Crafter.CppDOM-EventTypes.cppm +++ b/interfaces/Crafter.CppDOM-EventTypes.cppm @@ -44,30 +44,36 @@ export namespace Crafter { bool ctrlKey; bool shiftKey; bool metaKey; + MouseEvent(double clientX, double clientY, double screenX, double screenY, std::uint_fast32_t button, std::uint_fast32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) : clientX(clientX), clientY(clientY), screenX(screenX), screenY(screenY), button(button), buttons(buttons), altKey(altKey), ctrlKey(ctrlKey), shiftKey(shiftKey), metaKey(metaKey) {} }; struct InputEvent { std::string data; bool isComposing; + InputEvent(const char* data, bool isComposing) : data(data), isComposing(isComposing) {} }; struct WheelEvent : public MouseEvent { double deltaX; double deltaY; double deltaZ; + WheelEvent(double clientX, double clientY, double screenX, double screenY, std::uint_fast32_t button, std::uint_fast32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey, double deltaX, double deltaY, double deltaZ): MouseEvent(clientX, clientY, screenX, screenY, button, buttons, altKey, ctrlKey, shiftKey, metaKey), deltaX(deltaX), deltaY(deltaY), deltaZ(deltaZ) {} }; struct ResizeEvent { std::uint_fast32_t width; std::uint_fast32_t height; + ResizeEvent(std::uint_fast32_t width, std::uint_fast32_t height) : width(width), height(height) {} }; struct ScrollEvent { double scrollX; double scrollY; + ScrollEvent(double scrollX, double scrollY) : scrollX(scrollX), scrollY(scrollY) {} }; struct ChangeEvent { std::string value; + ChangeEvent(const char* value) : value(value) {} }; } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-HtmlElement.cppm b/interfaces/Crafter.CppDOM-HtmlElement.cppm index 6364e4c..8411b2c 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -20,14 +20,39 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA export module Crafter.CppDOM:HtmlElement; import std; -import :Bindings; +import :BindingsExport; +import :BindingsImport; import :EventTypes; namespace Crafter { export class HtmlElement { public: void* const ptr; - std::vector handlers; + std::vector clickHandlers; + std::vector mouseOverHandlers; + std::vector mouseOutHandlers; + std::vector mouseMoveHandlers; + std::vector mouseDownHandlers; + std::vector mouseUpHandlers; + std::vector focusHandlers; + std::vector blurHandlers; + std::vector keyDownHandlers; + std::vector keyUpHandlers; + std::vector keyPressHandlers; + std::vector changeHandlers; + std::vector submitHandlers; + std::vector inputHandlers; + std::vector resizeHandlers; + std::vector scrollHandlers; + std::vector contextMenuHandlers; + std::vector dragStartHandlers; + std::vector dragEndHandlers; + std::vector dropHandlers; + std::vector dragOverHandlers; + std::vector dragEnterHandlers; + std::vector dragLeaveHandlers; + std::vector wheelHandlers; + HtmlElement(const std::string_view id): ptr(CppDOMBindings::GetElementById(id)) { } @@ -38,89 +63,86 @@ namespace Crafter { CppDOMBindings::SetInnerHTML(ptr, html); } - // Event handling methods with event data - - // Mouse Events std::int32_t AddClickListener(std::function callback) { std::int32_t id = CppDOMBindings::clickHandlerMaxId++; - handlers.push_back(id); + clickHandlers.push_back(id); CppDOMBindings::clickHandlers->insert({id, callback}); CppDOMBindings::AddClickListener(ptr, id); return id; } void RemoveClickListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + clickHandlers.erase(std::remove(clickHandlers.begin(), clickHandlers.end(), id), clickHandlers.end()); CppDOMBindings::clickHandlers->erase(id); CppDOMBindings::RemoveClickListener(ptr, id); } std::int32_t AddMouseOverListener(std::function callback) { std::int32_t id = CppDOMBindings::mouseOverHandlerMaxId++; - handlers.push_back(id); + mouseOverHandlers.push_back(id); CppDOMBindings::mouseOverHandlers->insert({id, callback}); CppDOMBindings::AddMouseOverListener(ptr, id); return id; } void RemoveMouseOverListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + mouseOverHandlers.erase(std::remove(mouseOverHandlers.begin(), mouseOverHandlers.end(), id), mouseOverHandlers.end()); CppDOMBindings::mouseOverHandlers->erase(id); CppDOMBindings::RemoveMouseOverListener(ptr, id); } std::int32_t AddMouseOutListener(std::function callback) { std::int32_t id = CppDOMBindings::mouseOutHandlerMaxId++; - handlers.push_back(id); + mouseOutHandlers.push_back(id); CppDOMBindings::mouseOutHandlers->insert({id, callback}); CppDOMBindings::AddMouseOutListener(ptr, id); return id; } void RemoveMouseOutListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + mouseOutHandlers.erase(std::remove(mouseOutHandlers.begin(), mouseOutHandlers.end(), id), mouseOutHandlers.end()); CppDOMBindings::mouseOutHandlers->erase(id); CppDOMBindings::RemoveMouseOutListener(ptr, id); } std::int32_t AddMouseMoveListener(std::function callback) { std::int32_t id = CppDOMBindings::mouseMoveHandlerMaxId++; - handlers.push_back(id); + mouseMoveHandlers.push_back(id); CppDOMBindings::mouseMoveHandlers->insert({id, callback}); CppDOMBindings::AddMouseMoveListener(ptr, id); return id; } void RemoveMouseMoveListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + mouseMoveHandlers.erase(std::remove(mouseMoveHandlers.begin(), mouseMoveHandlers.end(), id), mouseMoveHandlers.end()); CppDOMBindings::mouseMoveHandlers->erase(id); CppDOMBindings::RemoveMouseMoveListener(ptr, id); } std::int32_t AddMouseDownListener(std::function callback) { std::int32_t id = CppDOMBindings::mouseDownHandlerMaxId++; - handlers.push_back(id); + mouseDownHandlers.push_back(id); CppDOMBindings::mouseDownHandlers->insert({id, callback}); CppDOMBindings::AddMouseDownListener(ptr, id); return id; } void RemoveMouseDownListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + mouseDownHandlers.erase(std::remove(mouseDownHandlers.begin(), mouseDownHandlers.end(), id), mouseDownHandlers.end()); CppDOMBindings::mouseDownHandlers->erase(id); CppDOMBindings::RemoveMouseDownListener(ptr, id); } std::int32_t AddMouseUpListener(std::function callback) { std::int32_t id = CppDOMBindings::mouseUpHandlerMaxId++; - handlers.push_back(id); + mouseUpHandlers.push_back(id); CppDOMBindings::mouseUpHandlers->insert({id, callback}); CppDOMBindings::AddMouseUpListener(ptr, id); return id; } void RemoveMouseUpListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + mouseUpHandlers.erase(std::remove(mouseUpHandlers.begin(), mouseUpHandlers.end(), id), mouseUpHandlers.end()); CppDOMBindings::mouseUpHandlers->erase(id); CppDOMBindings::RemoveMouseUpListener(ptr, id); } @@ -128,28 +150,28 @@ namespace Crafter { // Focus Events std::int32_t AddFocusListener(std::function callback) { std::int32_t id = CppDOMBindings::focusHandlerMaxId++; - handlers.push_back(id); + focusHandlers.push_back(id); CppDOMBindings::focusHandlers->insert({id, callback}); CppDOMBindings::AddFocusListener(ptr, id); return id; } void RemoveFocusListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + focusHandlers.erase(std::remove(focusHandlers.begin(), focusHandlers.end(), id), focusHandlers.end()); CppDOMBindings::focusHandlers->erase(id); CppDOMBindings::RemoveFocusListener(ptr, id); } std::int32_t AddBlurListener(std::function callback) { std::int32_t id = CppDOMBindings::blurHandlerMaxId++; - handlers.push_back(id); + blurHandlers.push_back(id); CppDOMBindings::blurHandlers->insert({id, callback}); CppDOMBindings::AddBlurListener(ptr, id); return id; } void RemoveBlurListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + blurHandlers.erase(std::remove(blurHandlers.begin(), blurHandlers.end(), id), blurHandlers.end()); CppDOMBindings::blurHandlers->erase(id); CppDOMBindings::RemoveBlurListener(ptr, id); } @@ -157,42 +179,42 @@ namespace Crafter { // Keyboard Events std::int32_t AddKeyDownListener(std::function callback) { std::int32_t id = CppDOMBindings::keyDownHandlerMaxId++; - handlers.push_back(id); + keyDownHandlers.push_back(id); CppDOMBindings::keyDownHandlers->insert({id, callback}); CppDOMBindings::AddKeyDownListener(ptr, id); return id; } void RemoveKeyDownListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + keyDownHandlers.erase(std::remove(keyDownHandlers.begin(), keyDownHandlers.end(), id), keyDownHandlers.end()); CppDOMBindings::keyDownHandlers->erase(id); CppDOMBindings::RemoveKeyDownListener(ptr, id); } std::int32_t AddKeyUpListener(std::function callback) { std::int32_t id = CppDOMBindings::keyUpHandlerMaxId++; - handlers.push_back(id); + keyUpHandlers.push_back(id); CppDOMBindings::keyUpHandlers->insert({id, callback}); CppDOMBindings::AddKeyUpListener(ptr, id); return id; } void RemoveKeyUpListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + keyUpHandlers.erase(std::remove(keyUpHandlers.begin(), keyUpHandlers.end(), id), keyUpHandlers.end()); CppDOMBindings::keyUpHandlers->erase(id); CppDOMBindings::RemoveKeyUpListener(ptr, id); } std::int32_t AddKeyPressListener(std::function callback) { std::int32_t id = CppDOMBindings::keyPressHandlerMaxId++; - handlers.push_back(id); + keyPressHandlers.push_back(id); CppDOMBindings::keyPressHandlers->insert({id, callback}); CppDOMBindings::AddKeyPressListener(ptr, id); return id; } void RemoveKeyPressListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + keyPressHandlers.erase(std::remove(keyPressHandlers.begin(), keyPressHandlers.end(), id), keyPressHandlers.end()); CppDOMBindings::keyPressHandlers->erase(id); CppDOMBindings::RemoveKeyPressListener(ptr, id); } @@ -200,70 +222,70 @@ namespace Crafter { // Form Events std::int32_t AddChangeListener(std::function callback) { std::int32_t id = CppDOMBindings::changeHandlerMaxId++; - handlers.push_back(id); + changeHandlers.push_back(id); CppDOMBindings::changeHandlers->insert({id, callback}); CppDOMBindings::AddChangeListener(ptr, id); return id; } void RemoveChangeListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + changeHandlers.erase(std::remove(changeHandlers.begin(), changeHandlers.end(), id), changeHandlers.end()); CppDOMBindings::changeHandlers->erase(id); CppDOMBindings::RemoveChangeListener(ptr, id); } std::int32_t AddSubmitListener(std::function callback) { std::int32_t id = CppDOMBindings::submitHandlerMaxId++; - handlers.push_back(id); + submitHandlers.push_back(id); CppDOMBindings::submitHandlers->insert({id, callback}); CppDOMBindings::AddSubmitListener(ptr, id); return id; } void RemoveSubmitListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + submitHandlers.erase(std::remove(submitHandlers.begin(), submitHandlers.end(), id), submitHandlers.end()); CppDOMBindings::submitHandlers->erase(id); CppDOMBindings::RemoveSubmitListener(ptr, id); } std::int32_t AddInputListener(std::function callback) { std::int32_t id = CppDOMBindings::inputHandlerMaxId++; - handlers.push_back(id); + inputHandlers.push_back(id); CppDOMBindings::inputHandlers->insert({id, callback}); CppDOMBindings::AddInputListener(ptr, id); return id; } void RemoveInputListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + inputHandlers.erase(std::remove(inputHandlers.begin(), inputHandlers.end(), id), inputHandlers.end()); CppDOMBindings::inputHandlers->erase(id); CppDOMBindings::RemoveInputListener(ptr, id); } std::int32_t AddResizeListener(std::function callback) { std::int32_t id = CppDOMBindings::resizeHandlerMaxId++; - handlers.push_back(id); + resizeHandlers.push_back(id); CppDOMBindings::resizeHandlers->insert({id, callback}); CppDOMBindings::AddResizeListener(ptr, id); return id; } void RemoveResizeListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + resizeHandlers.erase(std::remove(resizeHandlers.begin(), resizeHandlers.end(), id), resizeHandlers.end()); CppDOMBindings::resizeHandlers->erase(id); CppDOMBindings::RemoveResizeListener(ptr, id); } std::int32_t AddScrollListener(std::function callback) { std::int32_t id = CppDOMBindings::scrollHandlerMaxId++; - handlers.push_back(id); + scrollHandlers.push_back(id); CppDOMBindings::scrollHandlers->insert({id, callback}); CppDOMBindings::AddScrollListener(ptr, id); return id; } void RemoveScrollListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + scrollHandlers.erase(std::remove(scrollHandlers.begin(), scrollHandlers.end(), id), scrollHandlers.end()); CppDOMBindings::scrollHandlers->erase(id); CppDOMBindings::RemoveScrollListener(ptr, id); } @@ -271,14 +293,14 @@ namespace Crafter { // Context Menu Events std::int32_t AddContextMenuListener(std::function callback) { std::int32_t id = CppDOMBindings::contextMenuHandlerMaxId++; - handlers.push_back(id); + contextMenuHandlers.push_back(id); CppDOMBindings::contextMenuHandlers->insert({id, callback}); CppDOMBindings::AddContextMenuListener(ptr, id); return id; } void RemoveContextMenuListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + contextMenuHandlers.erase(std::remove(contextMenuHandlers.begin(), contextMenuHandlers.end(), id), contextMenuHandlers.end()); CppDOMBindings::contextMenuHandlers->erase(id); CppDOMBindings::RemoveContextMenuListener(ptr, id); } @@ -286,42 +308,42 @@ namespace Crafter { // Drag and Drop Events std::int32_t AddDragStartListener(std::function callback) { std::int32_t id = CppDOMBindings::dragStartHandlerMaxId++; - handlers.push_back(id); + dragStartHandlers.push_back(id); CppDOMBindings::dragStartHandlers->insert({id, callback}); CppDOMBindings::AddDragStartListener(ptr, id); return id; } void RemoveDragStartListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dragStartHandlers.erase(std::remove(dragStartHandlers.begin(), dragStartHandlers.end(), id), dragStartHandlers.end()); CppDOMBindings::dragStartHandlers->erase(id); CppDOMBindings::RemoveDragStartListener(ptr, id); } std::int32_t AddDragEndListener(std::function callback) { std::int32_t id = CppDOMBindings::dragEndHandlerMaxId++; - handlers.push_back(id); + dragEndHandlers.push_back(id); CppDOMBindings::dragEndHandlers->insert({id, callback}); CppDOMBindings::AddDragEndListener(ptr, id); return id; } void RemoveDragEndListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dragEndHandlers.erase(std::remove(dragEndHandlers.begin(), dragEndHandlers.end(), id), dragEndHandlers.end()); CppDOMBindings::dragEndHandlers->erase(id); CppDOMBindings::RemoveDragEndListener(ptr, id); } std::int32_t AddDropListener(std::function callback) { std::int32_t id = CppDOMBindings::dropHandlerMaxId++; - handlers.push_back(id); + dropHandlers.push_back(id); CppDOMBindings::dropHandlers->insert({id, callback}); CppDOMBindings::AddDropListener(ptr, id); return id; } void RemoveDropListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dropHandlers.erase(std::remove(dropHandlers.begin(), dropHandlers.end(), id), dropHandlers.end()); CppDOMBindings::dropHandlers->erase(id); CppDOMBindings::RemoveDropListener(ptr, id); } @@ -329,42 +351,42 @@ namespace Crafter { // Additional Drag Events std::int32_t AddDragOverListener(std::function callback) { std::int32_t id = CppDOMBindings::dragOverHandlerMaxId++; - handlers.push_back(id); + dragOverHandlers.push_back(id); CppDOMBindings::dragOverHandlers->insert({id, callback}); CppDOMBindings::AddDragOverListener(ptr, id); return id; } void RemoveDragOverListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dragOverHandlers.erase(std::remove(dragOverHandlers.begin(), dragOverHandlers.end(), id), dragOverHandlers.end()); CppDOMBindings::dragOverHandlers->erase(id); CppDOMBindings::RemoveDragOverListener(ptr, id); } std::int32_t AddDragEnterListener(std::function callback) { std::int32_t id = CppDOMBindings::dragEnterHandlerMaxId++; - handlers.push_back(id); + dragEnterHandlers.push_back(id); CppDOMBindings::dragEnterHandlers->insert({id, callback}); CppDOMBindings::AddDragEnterListener(ptr, id); return id; } void RemoveDragEnterListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dragEnterHandlers.erase(std::remove(dragEnterHandlers.begin(), dragEnterHandlers.end(), id), dragEnterHandlers.end()); CppDOMBindings::dragEnterHandlers->erase(id); CppDOMBindings::RemoveDragEnterListener(ptr, id); } std::int32_t AddDragLeaveListener(std::function callback) { std::int32_t id = CppDOMBindings::dragLeaveHandlerMaxId++; - handlers.push_back(id); + dragLeaveHandlers.push_back(id); CppDOMBindings::dragLeaveHandlers->insert({id, callback}); CppDOMBindings::AddDragLeaveListener(ptr, id); return id; } void RemoveDragLeaveListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + dragLeaveHandlers.erase(std::remove(dragLeaveHandlers.begin(), dragLeaveHandlers.end(), id), dragLeaveHandlers.end()); CppDOMBindings::dragLeaveHandlers->erase(id); CppDOMBindings::RemoveDragLeaveListener(ptr, id); } @@ -372,23 +394,116 @@ namespace Crafter { // Wheel Event std::int32_t AddWheelListener(std::function callback) { std::int32_t id = CppDOMBindings::wheelHandlerMaxId++; - handlers.push_back(id); + wheelHandlers.push_back(id); CppDOMBindings::wheelHandlers->insert({id, callback}); CppDOMBindings::AddWheelListener(ptr, id); return id; } void RemoveWheelListener(std::int32_t id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); + wheelHandlers.erase(std::remove(wheelHandlers.begin(), wheelHandlers.end(), id), wheelHandlers.end()); CppDOMBindings::wheelHandlers->erase(id); CppDOMBindings::RemoveWheelListener(ptr, id); } ~HtmlElement(){ - for(std::int32_t handler : handlers) { + // Clean up all handlers by type + for(std::int32_t handler : clickHandlers) { CppDOMBindings::clickHandlers->erase(handler); CppDOMBindings::RemoveClickListener(ptr, handler); } + for(std::int32_t handler : mouseOverHandlers) { + CppDOMBindings::mouseOverHandlers->erase(handler); + CppDOMBindings::RemoveMouseOverListener(ptr, handler); + } + for(std::int32_t handler : mouseOutHandlers) { + CppDOMBindings::mouseOutHandlers->erase(handler); + CppDOMBindings::RemoveMouseOutListener(ptr, handler); + } + for(std::int32_t handler : mouseMoveHandlers) { + CppDOMBindings::mouseMoveHandlers->erase(handler); + CppDOMBindings::RemoveMouseMoveListener(ptr, handler); + } + for(std::int32_t handler : mouseDownHandlers) { + CppDOMBindings::mouseDownHandlers->erase(handler); + CppDOMBindings::RemoveMouseDownListener(ptr, handler); + } + for(std::int32_t handler : mouseUpHandlers) { + CppDOMBindings::mouseUpHandlers->erase(handler); + CppDOMBindings::RemoveMouseUpListener(ptr, handler); + } + for(std::int32_t handler : focusHandlers) { + CppDOMBindings::focusHandlers->erase(handler); + CppDOMBindings::RemoveFocusListener(ptr, handler); + } + for(std::int32_t handler : blurHandlers) { + CppDOMBindings::blurHandlers->erase(handler); + CppDOMBindings::RemoveBlurListener(ptr, handler); + } + for(std::int32_t handler : keyDownHandlers) { + CppDOMBindings::keyDownHandlers->erase(handler); + CppDOMBindings::RemoveKeyDownListener(ptr, handler); + } + for(std::int32_t handler : keyUpHandlers) { + CppDOMBindings::keyUpHandlers->erase(handler); + CppDOMBindings::RemoveKeyUpListener(ptr, handler); + } + for(std::int32_t handler : keyPressHandlers) { + CppDOMBindings::keyPressHandlers->erase(handler); + CppDOMBindings::RemoveKeyPressListener(ptr, handler); + } + for(std::int32_t handler : changeHandlers) { + CppDOMBindings::changeHandlers->erase(handler); + CppDOMBindings::RemoveChangeListener(ptr, handler); + } + for(std::int32_t handler : submitHandlers) { + CppDOMBindings::submitHandlers->erase(handler); + CppDOMBindings::RemoveSubmitListener(ptr, handler); + } + for(std::int32_t handler : inputHandlers) { + CppDOMBindings::inputHandlers->erase(handler); + CppDOMBindings::RemoveInputListener(ptr, handler); + } + for(std::int32_t handler : resizeHandlers) { + CppDOMBindings::resizeHandlers->erase(handler); + CppDOMBindings::RemoveResizeListener(ptr, handler); + } + for(std::int32_t handler : scrollHandlers) { + CppDOMBindings::scrollHandlers->erase(handler); + CppDOMBindings::RemoveScrollListener(ptr, handler); + } + for(std::int32_t handler : contextMenuHandlers) { + CppDOMBindings::contextMenuHandlers->erase(handler); + CppDOMBindings::RemoveContextMenuListener(ptr, handler); + } + for(std::int32_t handler : dragStartHandlers) { + CppDOMBindings::dragStartHandlers->erase(handler); + CppDOMBindings::RemoveDragStartListener(ptr, handler); + } + for(std::int32_t handler : dragEndHandlers) { + CppDOMBindings::dragEndHandlers->erase(handler); + CppDOMBindings::RemoveDragEndListener(ptr, handler); + } + for(std::int32_t handler : dropHandlers) { + CppDOMBindings::dropHandlers->erase(handler); + CppDOMBindings::RemoveDropListener(ptr, handler); + } + for(std::int32_t handler : dragOverHandlers) { + CppDOMBindings::dragOverHandlers->erase(handler); + CppDOMBindings::RemoveDragOverListener(ptr, handler); + } + for(std::int32_t handler : dragEnterHandlers) { + CppDOMBindings::dragEnterHandlers->erase(handler); + CppDOMBindings::RemoveDragEnterListener(ptr, handler); + } + for(std::int32_t handler : dragLeaveHandlers) { + CppDOMBindings::dragLeaveHandlers->erase(handler); + CppDOMBindings::RemoveDragLeaveListener(ptr, handler); + } + for(std::int32_t handler : wheelHandlers) { + CppDOMBindings::wheelHandlers->erase(handler); + CppDOMBindings::RemoveWheelListener(ptr, handler); + } CppDOMBindings::FreeJs(ptr); } }; diff --git a/interfaces/Crafter.CppDOM.cppm b/interfaces/Crafter.CppDOM.cppm index d129ff2..1662b4f 100644 --- a/interfaces/Crafter.CppDOM.cppm +++ b/interfaces/Crafter.CppDOM.cppm @@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ export module Crafter.CppDOM; -export import :Bindings; export import :HtmlElement; -export import :EventTypes; \ No newline at end of file +export import :EventTypes; +export import :BindingsExport; +export import :BindingsImport; \ No newline at end of file diff --git a/project.json b/project.json index a56145a..dea2085 100644 --- a/project.json +++ b/project.json @@ -3,7 +3,7 @@ "configurations": [ { "name": "lib", - "interfaces": ["interfaces/Crafter.CppDOM-HtmlElement", "interfaces/Crafter.CppDOM", "interfaces/Crafter.CppDOM-Bindings", "interfaces/Crafter.CppDOM-EventTypes"], + "interfaces": ["interfaces/Crafter.CppDOM-HtmlElement", "interfaces/Crafter.CppDOM", "interfaces/Crafter.CppDOM-BindingsExport", "interfaces/Crafter.CppDOM-BindingsImport", "interfaces/Crafter.CppDOM-EventTypes"], "additional_files": ["additional/env.js"], "type":"library", "target":"wasm32-wasi"