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

Enhanced Event Handling Demo

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

Simple click event triggered!

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

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

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

Key pressed: {}

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

Ctrl key pressed

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

Shift key pressed

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

Alt key pressed

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

Input data: {} (composing: {})

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

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

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

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

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

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

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

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

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