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/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 e5ad748..0000000 --- a/examples/CompleteEventHandling/main.cpp +++ /dev/null @@ -1,77 +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/EnhancedEventHandling/main.cpp b/examples/EnhancedEventHandling/main.cpp new file mode 100644 index 0000000..fb89730 --- /dev/null +++ b/examples/EnhancedEventHandling/main.cpp @@ -0,0 +1,21 @@ +import Crafter.CppDOM; +using namespace Crafter; +import std; + +HtmlElement* body = new HtmlElement("body", "
" + "

Enhanced Event Handling Demo

" + "" + "
" + "
"); +HtmlElement* keyInput = new HtmlElement("keyInput"); +HtmlElement* output = new HtmlElement("output"); + +int main(){ + 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); + }); +} \ No newline at end of file diff --git a/examples/CompleteEventHandling/project.json b/examples/EnhancedEventHandling/project.json similarity index 100% rename from examples/CompleteEventHandling/project.json rename to examples/EnhancedEventHandling/project.json diff --git a/examples/CompleteEventHandling/run.sh b/examples/EnhancedEventHandling/run.sh similarity index 100% rename from examples/CompleteEventHandling/run.sh rename to examples/EnhancedEventHandling/run.sh 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 deleted file mode 100644 index 6177fd7..0000000 --- a/interfaces/Crafter.CppDOM-Bindings.cppm +++ /dev/null @@ -1,237 +0,0 @@ -/* -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:Bindings; -import std; - -export namespace Crafter::CppDOM::Bindings { - int clickHandlerMaxId = 0; - std::unordered_map>* clickHandlers = new std::unordered_map>(); - - int mouseOverHandlerMaxId = 0; - std::unordered_map>* mouseOverHandlers = new std::unordered_map>(); - - int mouseOutHandlerMaxId = 0; - std::unordered_map>* mouseOutHandlers = new std::unordered_map>(); - - int mouseMoveHandlerMaxId = 0; - std::unordered_map>* mouseMoveHandlers = new std::unordered_map>(); - - int focusHandlerMaxId = 0; - std::unordered_map>* focusHandlers = new std::unordered_map>(); - - int blurHandlerMaxId = 0; - std::unordered_map>* blurHandlers = new std::unordered_map>(); - - int keyDownHandlerMaxId = 0; - std::unordered_map>* keyDownHandlers = new std::unordered_map>(); - - int keyUpHandlerMaxId = 0; - std::unordered_map>* keyUpHandlers = new std::unordered_map>(); - - int keyPressHandlerMaxId = 0; - std::unordered_map>* keyPressHandlers = new std::unordered_map>(); - - int changeHandlerMaxId = 0; - 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>(); - - int resizeHandlerMaxId = 0; - std::unordered_map>* resizeHandlers = new std::unordered_map>(); - - int scrollHandlerMaxId = 0; - std::unordered_map>* scrollHandlers = new std::unordered_map>(); - - int contextMenuHandlerMaxId = 0; - std::unordered_map>* contextMenuHandlers = new std::unordered_map>(); - - int dragStartHandlerMaxId = 0; - std::unordered_map>* dragStartHandlers = new std::unordered_map>(); - - int dragEndHandlerMaxId = 0; - std::unordered_map>* dragEndHandlers = new std::unordered_map>(); - - int dropHandlerMaxId = 0; - std::unordered_map>* dropHandlers = 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("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("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); - - __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); -} - -extern "C" { - __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(int a) { - Crafter::CppDOM::Bindings::clickHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteMouseOverHandler"))) void ExecuteMouseOverHandler(int a) { - Crafter::CppDOM::Bindings::mouseOverHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteMouseOutHandler"))) void ExecuteMouseOutHandler(int a) { - Crafter::CppDOM::Bindings::mouseOutHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteMouseMoveHandler"))) void ExecuteMouseMoveHandler(int a) { - Crafter::CppDOM::Bindings::mouseMoveHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteFocusHandler"))) void ExecuteFocusHandler(int a) { - Crafter::CppDOM::Bindings::focusHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteBlurHandler"))) void ExecuteBlurHandler(int a) { - Crafter::CppDOM::Bindings::blurHandlers->find(static_cast(a))->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("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("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("ExecuteChangeHandler"))) void ExecuteChangeHandler(int a) { - Crafter::CppDOM::Bindings::changeHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteSubmitHandler"))) void ExecuteSubmitHandler(int a) { - Crafter::CppDOM::Bindings::submitHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteInputHandler"))) void ExecuteInputHandler(int a) { - Crafter::CppDOM::Bindings::inputHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteLoadHandler"))) void ExecuteLoadHandler(int a) { - Crafter::CppDOM::Bindings::loadHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteErrorHandler"))) void ExecuteErrorHandler(int a) { - Crafter::CppDOM::Bindings::errorHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteResizeHandler"))) void ExecuteResizeHandler(int a) { - Crafter::CppDOM::Bindings::resizeHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteScrollHandler"))) void ExecuteScrollHandler(int a) { - Crafter::CppDOM::Bindings::scrollHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteContextMenuHandler"))) void ExecuteContextMenuHandler(int a) { - Crafter::CppDOM::Bindings::contextMenuHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteDragStartHandler"))) void ExecuteDragStartHandler(int a) { - Crafter::CppDOM::Bindings::dragStartHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteDragEndHandler"))) void ExecuteDragEndHandler(int a) { - Crafter::CppDOM::Bindings::dragEndHandlers->find(static_cast(a))->second(); - } - - __attribute__((export_name("ExecuteDropHandler"))) void ExecuteDropHandler(int a) { - Crafter::CppDOM::Bindings::dropHandlers->find(static_cast(a))->second(); - } -} \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-BindingsExport.cppm b/interfaces/Crafter.CppDOM-BindingsExport.cppm new file mode 100644 index 0000000..7ebe266 --- /dev/null +++ b/interfaces/Crafter.CppDOM-BindingsExport.cppm @@ -0,0 +1,204 @@ +/* +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:BindingsExport; +import std; +import :EventTypes; + +export namespace Crafter::CppDOMBindings { + int clickHandlerMaxId = 0; + std::unordered_map>* clickHandlers = new std::unordered_map>(); + + int mouseOverHandlerMaxId = 0; + std::unordered_map>* mouseOverHandlers = new std::unordered_map>(); + + int mouseOutHandlerMaxId = 0; + std::unordered_map>* mouseOutHandlers = new std::unordered_map>(); + + 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>(); + + int blurHandlerMaxId = 0; + std::unordered_map>* blurHandlers = new std::unordered_map>(); + + int keyDownHandlerMaxId = 0; + std::unordered_map>* keyDownHandlers = new std::unordered_map>(); + + int keyUpHandlerMaxId = 0; + std::unordered_map>* keyUpHandlers = new std::unordered_map>(); + + int keyPressHandlerMaxId = 0; + std::unordered_map>* keyPressHandlers = new std::unordered_map>(); + + int changeHandlerMaxId = 0; + 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 resizeHandlerMaxId = 0; + std::unordered_map>* resizeHandlers = new std::unordered_map>(); + + int scrollHandlerMaxId = 0; + std::unordered_map>* scrollHandlers = new std::unordered_map>(); + + int contextMenuHandlerMaxId = 0; + std::unordered_map>* contextMenuHandlers = new std::unordered_map>(); + + int dragStartHandlerMaxId = 0; + std::unordered_map>* dragStartHandlers = new std::unordered_map>(); + + int dragEndHandlerMaxId = 0; + std::unordered_map>* dragEndHandlers = new std::unordered_map>(); + + int dropHandlerMaxId = 0; + 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>(); +} + +extern "C" { + __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(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseOverHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteMouseOutHandler"))) void ExecuteMouseOutHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseOutHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteMouseMoveHandler"))) void ExecuteMouseMoveHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseMoveHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteMouseDownHandler"))) void ExecuteMouseDownHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseDownHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteMouseUpHandler"))) void ExecuteMouseUpHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::mouseUpHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteFocusHandler"))) void ExecuteFocusHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::focusHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteBlurHandler"))) void ExecuteBlurHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::blurHandlers->find(handlerID)->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("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("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("ExecuteChangeHandler"))) void ExecuteChangeHandler(std::int32_t handlerID, const char* value) { + Crafter::CppDOMBindings::changeHandlers->find(handlerID)->second(Crafter::ChangeEvent(value)); + } + + __attribute__((export_name("ExecuteSubmitHandler"))) void ExecuteSubmitHandler(std::int32_t handlerID) { + Crafter::CppDOMBindings::submitHandlers->find(handlerID)->second(); + } + + __attribute__((export_name("ExecuteInputHandler"))) void ExecuteInputHandler(std::int32_t handlerID, const char* data, bool isComposing) { + 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::CppDOMBindings::resizeHandlers->find(handlerID)->second(Crafter::ResizeEvent(width, height)); + } + + __attribute__((export_name("ExecuteScrollHandler"))) void ExecuteScrollHandler(std::int32_t handlerID, double scrollX, double scrollY) { + 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::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::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::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::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::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::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::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::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 new file mode 100644 index 0000000..ad92c2f --- /dev/null +++ b/interfaces/Crafter.CppDOM-EventTypes.cppm @@ -0,0 +1,79 @@ +/* +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; + 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 d79185f..8411b2c 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -20,312 +20,491 @@ 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; - HtmlElement(const std::string_view id): ptr(CppDOM::Bindings::GetElementById(id)) { + 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)) { } - 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++; - handlers.push_back(id); - CppDOM::Bindings::clickHandlers->insert({id, callback}); - CppDOM::Bindings::AddClickListener(ptr, id); + std::int32_t AddClickListener(std::function callback) { + std::int32_t id = CppDOMBindings::clickHandlerMaxId++; + clickHandlers.push_back(id); + CppDOMBindings::clickHandlers->insert({id, callback}); + CppDOMBindings::AddClickListener(ptr, id); return id; } - void RemoveClickListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::clickHandlers->erase(id); - CppDOM::Bindings::RemoveClickListener(ptr, id); + void RemoveClickListener(std::int32_t id) { + clickHandlers.erase(std::remove(clickHandlers.begin(), clickHandlers.end(), id), clickHandlers.end()); + CppDOMBindings::clickHandlers->erase(id); + CppDOMBindings::RemoveClickListener(ptr, id); } - int AddMouseOverListener(std::function callback) { - int id = CppDOM::Bindings::mouseOverHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::mouseOverHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseOverListener(ptr, id); + std::int32_t AddMouseOverListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseOverHandlerMaxId++; + mouseOverHandlers.push_back(id); + CppDOMBindings::mouseOverHandlers->insert({id, callback}); + CppDOMBindings::AddMouseOverListener(ptr, id); return id; } - void RemoveMouseOverListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseOverHandlers->erase(id); - CppDOM::Bindings::RemoveMouseOverListener(ptr, id); + void RemoveMouseOverListener(std::int32_t id) { + mouseOverHandlers.erase(std::remove(mouseOverHandlers.begin(), mouseOverHandlers.end(), id), mouseOverHandlers.end()); + CppDOMBindings::mouseOverHandlers->erase(id); + CppDOMBindings::RemoveMouseOverListener(ptr, id); } - int AddMouseOutListener(std::function callback) { - int id = CppDOM::Bindings::mouseOutHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::mouseOutHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseOutListener(ptr, id); + std::int32_t AddMouseOutListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseOutHandlerMaxId++; + mouseOutHandlers.push_back(id); + CppDOMBindings::mouseOutHandlers->insert({id, callback}); + CppDOMBindings::AddMouseOutListener(ptr, id); return id; } - void RemoveMouseOutListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseOutHandlers->erase(id); - CppDOM::Bindings::RemoveMouseOutListener(ptr, id); + void RemoveMouseOutListener(std::int32_t id) { + mouseOutHandlers.erase(std::remove(mouseOutHandlers.begin(), mouseOutHandlers.end(), id), mouseOutHandlers.end()); + CppDOMBindings::mouseOutHandlers->erase(id); + CppDOMBindings::RemoveMouseOutListener(ptr, id); } - int AddMouseMoveListener(std::function callback) { - int id = CppDOM::Bindings::mouseMoveHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::mouseMoveHandlers->insert({id, callback}); - CppDOM::Bindings::AddMouseMoveListener(ptr, id); + std::int32_t AddMouseMoveListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseMoveHandlerMaxId++; + mouseMoveHandlers.push_back(id); + CppDOMBindings::mouseMoveHandlers->insert({id, callback}); + CppDOMBindings::AddMouseMoveListener(ptr, id); return id; } - void RemoveMouseMoveListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::mouseMoveHandlers->erase(id); - CppDOM::Bindings::RemoveMouseMoveListener(ptr, id); + void RemoveMouseMoveListener(std::int32_t id) { + mouseMoveHandlers.erase(std::remove(mouseMoveHandlers.begin(), mouseMoveHandlers.end(), id), mouseMoveHandlers.end()); + CppDOMBindings::mouseMoveHandlers->erase(id); + CppDOMBindings::RemoveMouseMoveListener(ptr, id); } - int AddFocusListener(std::function callback) { - int id = CppDOM::Bindings::focusHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::focusHandlers->insert({id, callback}); - CppDOM::Bindings::AddFocusListener(ptr, id); + std::int32_t AddMouseDownListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseDownHandlerMaxId++; + mouseDownHandlers.push_back(id); + CppDOMBindings::mouseDownHandlers->insert({id, callback}); + CppDOMBindings::AddMouseDownListener(ptr, id); return id; } - void RemoveFocusListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::focusHandlers->erase(id); - CppDOM::Bindings::RemoveFocusListener(ptr, id); + void RemoveMouseDownListener(std::int32_t id) { + mouseDownHandlers.erase(std::remove(mouseDownHandlers.begin(), mouseDownHandlers.end(), id), mouseDownHandlers.end()); + CppDOMBindings::mouseDownHandlers->erase(id); + CppDOMBindings::RemoveMouseDownListener(ptr, id); } - int AddBlurListener(std::function callback) { - int id = CppDOM::Bindings::blurHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::blurHandlers->insert({id, callback}); - CppDOM::Bindings::AddBlurListener(ptr, id); + std::int32_t AddMouseUpListener(std::function callback) { + std::int32_t id = CppDOMBindings::mouseUpHandlerMaxId++; + mouseUpHandlers.push_back(id); + CppDOMBindings::mouseUpHandlers->insert({id, callback}); + CppDOMBindings::AddMouseUpListener(ptr, id); return id; } - void RemoveBlurListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::blurHandlers->erase(id); - CppDOM::Bindings::RemoveBlurListener(ptr, id); + void RemoveMouseUpListener(std::int32_t id) { + mouseUpHandlers.erase(std::remove(mouseUpHandlers.begin(), mouseUpHandlers.end(), id), mouseUpHandlers.end()); + CppDOMBindings::mouseUpHandlers->erase(id); + CppDOMBindings::RemoveMouseUpListener(ptr, id); } - int AddKeyDownListener(std::function callback) { - int id = CppDOM::Bindings::keyDownHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::keyDownHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyDownListener(ptr, id); + // Focus Events + std::int32_t AddFocusListener(std::function callback) { + std::int32_t id = CppDOMBindings::focusHandlerMaxId++; + focusHandlers.push_back(id); + CppDOMBindings::focusHandlers->insert({id, callback}); + CppDOMBindings::AddFocusListener(ptr, id); return id; } - void RemoveKeyDownListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyDownHandlers->erase(id); - CppDOM::Bindings::RemoveKeyDownListener(ptr, id); + void RemoveFocusListener(std::int32_t id) { + focusHandlers.erase(std::remove(focusHandlers.begin(), focusHandlers.end(), id), focusHandlers.end()); + CppDOMBindings::focusHandlers->erase(id); + CppDOMBindings::RemoveFocusListener(ptr, id); } - int AddKeyUpListener(std::function callback) { - int id = CppDOM::Bindings::keyUpHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::keyUpHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyUpListener(ptr, id); + std::int32_t AddBlurListener(std::function callback) { + std::int32_t id = CppDOMBindings::blurHandlerMaxId++; + blurHandlers.push_back(id); + CppDOMBindings::blurHandlers->insert({id, callback}); + CppDOMBindings::AddBlurListener(ptr, id); return id; } - void RemoveKeyUpListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyUpHandlers->erase(id); - CppDOM::Bindings::RemoveKeyUpListener(ptr, id); + void RemoveBlurListener(std::int32_t id) { + blurHandlers.erase(std::remove(blurHandlers.begin(), blurHandlers.end(), id), blurHandlers.end()); + CppDOMBindings::blurHandlers->erase(id); + CppDOMBindings::RemoveBlurListener(ptr, id); } - int AddKeyPressListener(std::function callback) { - int id = CppDOM::Bindings::keyPressHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::keyPressHandlers->insert({id, callback}); - CppDOM::Bindings::AddKeyPressListener(ptr, id); + // Keyboard Events + std::int32_t AddKeyDownListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyDownHandlerMaxId++; + keyDownHandlers.push_back(id); + CppDOMBindings::keyDownHandlers->insert({id, callback}); + CppDOMBindings::AddKeyDownListener(ptr, id); return id; } - void RemoveKeyPressListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::keyPressHandlers->erase(id); - CppDOM::Bindings::RemoveKeyPressListener(ptr, id); + void RemoveKeyDownListener(std::int32_t id) { + keyDownHandlers.erase(std::remove(keyDownHandlers.begin(), keyDownHandlers.end(), id), keyDownHandlers.end()); + CppDOMBindings::keyDownHandlers->erase(id); + CppDOMBindings::RemoveKeyDownListener(ptr, id); } - int AddChangeListener(std::function callback) { - int id = CppDOM::Bindings::changeHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::changeHandlers->insert({id, callback}); - CppDOM::Bindings::AddChangeListener(ptr, id); + std::int32_t AddKeyUpListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyUpHandlerMaxId++; + keyUpHandlers.push_back(id); + CppDOMBindings::keyUpHandlers->insert({id, callback}); + CppDOMBindings::AddKeyUpListener(ptr, id); return id; } - void RemoveChangeListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::changeHandlers->erase(id); - CppDOM::Bindings::RemoveChangeListener(ptr, id); + void RemoveKeyUpListener(std::int32_t id) { + keyUpHandlers.erase(std::remove(keyUpHandlers.begin(), keyUpHandlers.end(), id), keyUpHandlers.end()); + CppDOMBindings::keyUpHandlers->erase(id); + CppDOMBindings::RemoveKeyUpListener(ptr, id); } - int AddSubmitListener(std::function callback) { - int id = CppDOM::Bindings::submitHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::submitHandlers->insert({id, callback}); - CppDOM::Bindings::AddSubmitListener(ptr, id); + std::int32_t AddKeyPressListener(std::function callback) { + std::int32_t id = CppDOMBindings::keyPressHandlerMaxId++; + keyPressHandlers.push_back(id); + CppDOMBindings::keyPressHandlers->insert({id, callback}); + CppDOMBindings::AddKeyPressListener(ptr, id); return id; } - void RemoveSubmitListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::submitHandlers->erase(id); - CppDOM::Bindings::RemoveSubmitListener(ptr, id); + void RemoveKeyPressListener(std::int32_t id) { + keyPressHandlers.erase(std::remove(keyPressHandlers.begin(), keyPressHandlers.end(), id), keyPressHandlers.end()); + CppDOMBindings::keyPressHandlers->erase(id); + CppDOMBindings::RemoveKeyPressListener(ptr, id); } - int AddInputListener(std::function callback) { - int id = CppDOM::Bindings::inputHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::inputHandlers->insert({id, callback}); - CppDOM::Bindings::AddInputListener(ptr, id); + // Form Events + std::int32_t AddChangeListener(std::function callback) { + std::int32_t id = CppDOMBindings::changeHandlerMaxId++; + changeHandlers.push_back(id); + CppDOMBindings::changeHandlers->insert({id, callback}); + CppDOMBindings::AddChangeListener(ptr, id); return id; } - void RemoveInputListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::inputHandlers->erase(id); - CppDOM::Bindings::RemoveInputListener(ptr, id); + void RemoveChangeListener(std::int32_t id) { + changeHandlers.erase(std::remove(changeHandlers.begin(), changeHandlers.end(), id), changeHandlers.end()); + CppDOMBindings::changeHandlers->erase(id); + CppDOMBindings::RemoveChangeListener(ptr, id); } - int AddLoadListener(std::function callback) { - int id = CppDOM::Bindings::loadHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::loadHandlers->insert({id, callback}); - CppDOM::Bindings::AddLoadListener(ptr, id); + std::int32_t AddSubmitListener(std::function callback) { + std::int32_t id = CppDOMBindings::submitHandlerMaxId++; + submitHandlers.push_back(id); + CppDOMBindings::submitHandlers->insert({id, callback}); + CppDOMBindings::AddSubmitListener(ptr, id); return id; } - void RemoveLoadListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::loadHandlers->erase(id); - CppDOM::Bindings::RemoveLoadListener(ptr, id); + void RemoveSubmitListener(std::int32_t id) { + submitHandlers.erase(std::remove(submitHandlers.begin(), submitHandlers.end(), id), submitHandlers.end()); + CppDOMBindings::submitHandlers->erase(id); + CppDOMBindings::RemoveSubmitListener(ptr, id); } - int AddErrorListener(std::function callback) { - int id = CppDOM::Bindings::errorHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::errorHandlers->insert({id, callback}); - CppDOM::Bindings::AddErrorListener(ptr, id); + std::int32_t AddInputListener(std::function callback) { + std::int32_t id = CppDOMBindings::inputHandlerMaxId++; + inputHandlers.push_back(id); + CppDOMBindings::inputHandlers->insert({id, callback}); + CppDOMBindings::AddInputListener(ptr, id); return id; } - void RemoveErrorListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::errorHandlers->erase(id); - CppDOM::Bindings::RemoveErrorListener(ptr, id); + void RemoveInputListener(std::int32_t id) { + inputHandlers.erase(std::remove(inputHandlers.begin(), inputHandlers.end(), id), inputHandlers.end()); + CppDOMBindings::inputHandlers->erase(id); + CppDOMBindings::RemoveInputListener(ptr, id); } - int AddResizeListener(std::function callback) { - int id = CppDOM::Bindings::resizeHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::resizeHandlers->insert({id, callback}); - CppDOM::Bindings::AddResizeListener(ptr, id); + std::int32_t AddResizeListener(std::function callback) { + std::int32_t id = CppDOMBindings::resizeHandlerMaxId++; + resizeHandlers.push_back(id); + CppDOMBindings::resizeHandlers->insert({id, callback}); + CppDOMBindings::AddResizeListener(ptr, id); return id; } - void RemoveResizeListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::resizeHandlers->erase(id); - CppDOM::Bindings::RemoveResizeListener(ptr, id); + void RemoveResizeListener(std::int32_t id) { + resizeHandlers.erase(std::remove(resizeHandlers.begin(), resizeHandlers.end(), id), resizeHandlers.end()); + CppDOMBindings::resizeHandlers->erase(id); + CppDOMBindings::RemoveResizeListener(ptr, id); } - int AddScrollListener(std::function callback) { - int id = CppDOM::Bindings::scrollHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::scrollHandlers->insert({id, callback}); - CppDOM::Bindings::AddScrollListener(ptr, id); + std::int32_t AddScrollListener(std::function callback) { + std::int32_t id = CppDOMBindings::scrollHandlerMaxId++; + scrollHandlers.push_back(id); + CppDOMBindings::scrollHandlers->insert({id, callback}); + CppDOMBindings::AddScrollListener(ptr, id); return id; } - void RemoveScrollListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::scrollHandlers->erase(id); - CppDOM::Bindings::RemoveScrollListener(ptr, id); + void RemoveScrollListener(std::int32_t id) { + scrollHandlers.erase(std::remove(scrollHandlers.begin(), scrollHandlers.end(), id), scrollHandlers.end()); + CppDOMBindings::scrollHandlers->erase(id); + CppDOMBindings::RemoveScrollListener(ptr, id); } - int AddContextMenuListener(std::function callback) { - int id = CppDOM::Bindings::contextMenuHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::contextMenuHandlers->insert({id, callback}); - CppDOM::Bindings::AddContextMenuListener(ptr, id); + // Context Menu Events + std::int32_t AddContextMenuListener(std::function callback) { + std::int32_t id = CppDOMBindings::contextMenuHandlerMaxId++; + contextMenuHandlers.push_back(id); + CppDOMBindings::contextMenuHandlers->insert({id, callback}); + CppDOMBindings::AddContextMenuListener(ptr, id); return id; } - void RemoveContextMenuListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::contextMenuHandlers->erase(id); - CppDOM::Bindings::RemoveContextMenuListener(ptr, id); + void RemoveContextMenuListener(std::int32_t id) { + contextMenuHandlers.erase(std::remove(contextMenuHandlers.begin(), contextMenuHandlers.end(), id), contextMenuHandlers.end()); + CppDOMBindings::contextMenuHandlers->erase(id); + CppDOMBindings::RemoveContextMenuListener(ptr, id); } - int AddDragStartListener(std::function callback) { - int id = CppDOM::Bindings::dragStartHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::dragStartHandlers->insert({id, callback}); - CppDOM::Bindings::AddDragStartListener(ptr, id); + // Drag and Drop Events + std::int32_t AddDragStartListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragStartHandlerMaxId++; + dragStartHandlers.push_back(id); + CppDOMBindings::dragStartHandlers->insert({id, callback}); + CppDOMBindings::AddDragStartListener(ptr, id); return id; } - void RemoveDragStartListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dragStartHandlers->erase(id); - CppDOM::Bindings::RemoveDragStartListener(ptr, id); + void RemoveDragStartListener(std::int32_t id) { + dragStartHandlers.erase(std::remove(dragStartHandlers.begin(), dragStartHandlers.end(), id), dragStartHandlers.end()); + CppDOMBindings::dragStartHandlers->erase(id); + CppDOMBindings::RemoveDragStartListener(ptr, id); } - int AddDragEndListener(std::function callback) { - int id = CppDOM::Bindings::dragEndHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::dragEndHandlers->insert({id, callback}); - CppDOM::Bindings::AddDragEndListener(ptr, id); + std::int32_t AddDragEndListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragEndHandlerMaxId++; + dragEndHandlers.push_back(id); + CppDOMBindings::dragEndHandlers->insert({id, callback}); + CppDOMBindings::AddDragEndListener(ptr, id); return id; } - void RemoveDragEndListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dragEndHandlers->erase(id); - CppDOM::Bindings::RemoveDragEndListener(ptr, id); + void RemoveDragEndListener(std::int32_t id) { + dragEndHandlers.erase(std::remove(dragEndHandlers.begin(), dragEndHandlers.end(), id), dragEndHandlers.end()); + CppDOMBindings::dragEndHandlers->erase(id); + CppDOMBindings::RemoveDragEndListener(ptr, id); } - int AddDropListener(std::function callback) { - int id = CppDOM::Bindings::dropHandlerMaxId++; - handlers.push_back(id); - CppDOM::Bindings::dropHandlers->insert({id, callback}); - CppDOM::Bindings::AddDropListener(ptr, id); + std::int32_t AddDropListener(std::function callback) { + std::int32_t id = CppDOMBindings::dropHandlerMaxId++; + dropHandlers.push_back(id); + CppDOMBindings::dropHandlers->insert({id, callback}); + CppDOMBindings::AddDropListener(ptr, id); return id; } - void RemoveDropListener(int id) { - handlers.erase(std::remove(handlers.begin(), handlers.end(), id), handlers.end()); - CppDOM::Bindings::dropHandlers->erase(id); - CppDOM::Bindings::RemoveDropListener(ptr, id); + void RemoveDropListener(std::int32_t id) { + dropHandlers.erase(std::remove(dropHandlers.begin(), dropHandlers.end(), id), dropHandlers.end()); + CppDOMBindings::dropHandlers->erase(id); + CppDOMBindings::RemoveDropListener(ptr, id); + } + + // Additional Drag Events + std::int32_t AddDragOverListener(std::function callback) { + std::int32_t id = CppDOMBindings::dragOverHandlerMaxId++; + dragOverHandlers.push_back(id); + CppDOMBindings::dragOverHandlers->insert({id, callback}); + CppDOMBindings::AddDragOverListener(ptr, id); + return id; + } + + void RemoveDragOverListener(std::int32_t id) { + 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++; + dragEnterHandlers.push_back(id); + CppDOMBindings::dragEnterHandlers->insert({id, callback}); + CppDOMBindings::AddDragEnterListener(ptr, id); + return id; + } + + void RemoveDragEnterListener(std::int32_t id) { + 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++; + dragLeaveHandlers.push_back(id); + CppDOMBindings::dragLeaveHandlers->insert({id, callback}); + CppDOMBindings::AddDragLeaveListener(ptr, id); + return id; + } + + void RemoveDragLeaveListener(std::int32_t id) { + dragLeaveHandlers.erase(std::remove(dragLeaveHandlers.begin(), dragLeaveHandlers.end(), id), dragLeaveHandlers.end()); + CppDOMBindings::dragLeaveHandlers->erase(id); + CppDOMBindings::RemoveDragLeaveListener(ptr, id); + } + + // Wheel Event + std::int32_t AddWheelListener(std::function callback) { + std::int32_t id = CppDOMBindings::wheelHandlerMaxId++; + wheelHandlers.push_back(id); + CppDOMBindings::wheelHandlers->insert({id, callback}); + CppDOMBindings::AddWheelListener(ptr, id); + return id; + } + + void RemoveWheelListener(std::int32_t id) { + wheelHandlers.erase(std::remove(wheelHandlers.begin(), wheelHandlers.end(), id), wheelHandlers.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); + // Clean up all handlers by type + for(std::int32_t handler : clickHandlers) { + CppDOMBindings::clickHandlers->erase(handler); + CppDOMBindings::RemoveClickListener(ptr, handler); } - CppDOM::Bindings::FreeJs(ptr); + 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); } }; } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM.cppm b/interfaces/Crafter.CppDOM.cppm index b1f2e0b..1662b4f 100644 --- a/interfaces/Crafter.CppDOM.cppm +++ b/interfaces/Crafter.CppDOM.cppm @@ -19,5 +19,7 @@ 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; +export import :BindingsExport; +export import :BindingsImport; \ No newline at end of file diff --git a/project.json b/project.json index 330c796..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": ["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" @@ -14,4 +14,4 @@ "debug": true } ] -} +} \ No newline at end of file