diff --git a/additional/env.js b/additional/env.js index b73c49b..0e431be 100644 --- a/additional/env.js +++ b/additional/env.js @@ -59,7 +59,7 @@ function addClickListener(ptr, handlerID) { // Create a handler that will trigger a notification to C++ const handler = function (event) { const { ExecuteClickHandler } = window.crafter_webbuild_wasi.instance.exports; - ExecuteClickHandler(handlerID); + ExecuteClickHandler(handlerID, event.clientX, event.clientY, event.screenX, event.screenY, event.button, event.buttons, event.altKey, event.ctrlKey, event.shiftKey, event.metaKey); }; eventHandlers.set(`${ptr}-${handlerID}`, handler); diff --git a/examples/AllEventHandling/README.md b/examples/AllEventHandling/README.md new file mode 100644 index 0000000..ce5d58b --- /dev/null +++ b/examples/AllEventHandling/README.md @@ -0,0 +1,50 @@ +# All Event Handling Example + +This example demonstrates all available event types in Crafter.CppDOM: + +## Events Demonstrated + +### Mouse Events +- Click +- Mouse Over +- Mouse Out +- Mouse Move +- Mouse Down +- Mouse Up + +### Keyboard Events +- Key Down +- Key Up +- Key Press + +### Focus Events +- Focus +- Blur + +### Form Events +- Input +- Change + +### Window Events +- Resize +- Scroll +- Context Menu + +### Drag and Drop Events +- Drag Start +- Drag End +- Drag Over +- Drag Enter +- Drag Leave +- Drop + +### Wheel Events +- Wheel (Mouse wheel scrolling) + +## How to Run + +1. Build the project using the build system +2. Run the executable with `./run.sh` +3. Open your browser to `http://localhost:8080` + +The demo will show various event handlers in action through interactive elements. \ No newline at end of file diff --git a/examples/AllEventHandling/main.cpp b/examples/AllEventHandling/main.cpp new file mode 100644 index 0000000..c673361 --- /dev/null +++ b/examples/AllEventHandling/main.cpp @@ -0,0 +1,189 @@ +/* + * Enhanced Event Handling Demo + * This example showcases all available event types in Crafter.CppDOM + */ + +import Crafter.CppDOM; +using namespace Crafter; +import std; + +// Create the main container element +HtmlElement* body = new HtmlElement("body", "
" + "

Enhanced Event Handling Demo

" + "
" + "
" + "

Mouse Events

" + "" + "
" + "
" + "
" + "

Keyboard Events

" + "" + "
" + "
" + "
" + "

Focus Events

" + "" + "
" + "
" + "
" + "

Form Events

" + "" + "" + "
" + "
" + "
" + "

Window Events

" + "
" + "
" + "
" + "

Drag & Drop Events

" + "
Drag Me!
" + "
Drop Here
" + "
" + "
" + "
" + "

Wheel Events

" + "
Scroll here
" + "
" + "
" + "
" + "
"); + +// Get references to elements +HtmlElement* mouseButton = new HtmlElement("mouseButton"); +HtmlElement* mouseOutput = new HtmlElement("mouseOutput"); +HtmlElement* keyInput = new HtmlElement("keyInput"); +HtmlElement* keyOutput = new HtmlElement("keyOutput"); +HtmlElement* focusInput = new HtmlElement("focusInput"); +HtmlElement* focusOutput = new HtmlElement("focusOutput"); +HtmlElement* formInput = new HtmlElement("formInput"); +HtmlElement* formSelect = new HtmlElement("formSelect"); +HtmlElement* formOutput = new HtmlElement("formOutput"); +HtmlElement* windowOutput = new HtmlElement("windowOutput"); +HtmlElement* dragSource = new HtmlElement("dragSource"); +HtmlElement* dropTarget = new HtmlElement("dropTarget"); +HtmlElement* dragOutput = new HtmlElement("dragOutput"); +HtmlElement* wheelContainer = new HtmlElement("wheelContainer"); +HtmlElement* wheelOutput = new HtmlElement("wheelOutput"); + +int main() { + // Mouse Events + mouseButton->AddClickListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Click: X={}, Y={}

", event.clientX, event.clientY)); + }); + + mouseButton->AddMouseOverListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Mouse Over: X={}, Y={}

", event.clientX, event.clientY)); + }); + + mouseButton->AddMouseOutListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Mouse Out: X={}, Y={}

", event.clientX, event.clientY)); + }); + + mouseButton->AddMouseMoveListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Mouse Move: X={}, Y={}

", event.clientX, event.clientY)); + }); + + mouseButton->AddMouseDownListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Mouse Down: Button={}, X={}, Y={}

", event.button, event.clientX, event.clientY)); + }); + + mouseButton->AddMouseUpListener([&](MouseEvent event) { + mouseOutput->SetInnerHTML(std::format("

Mouse Up: Button={}, X={}, Y={}

", event.button, event.clientX, event.clientY)); + }); + + // Keyboard Events + keyInput->AddKeyDownListener([&](KeyboardEvent event) { + std::string keyInfo = std::format("

Key Down: Key='{}', Code={}, Ctrl={}, Shift={}, Alt={}

", + event.key, event.keyCode, event.ctrlKey, event.shiftKey, event.altKey); + keyOutput->SetInnerHTML(keyInfo); + }); + + keyInput->AddKeyUpListener([&](KeyboardEvent event) { + std::string keyInfo = std::format("

Key Up: Key='{}', Code={}, Ctrl={}, Shift={}, Alt={}

", + event.key, event.keyCode, event.ctrlKey, event.shiftKey, event.altKey); + keyOutput->SetInnerHTML(keyInfo); + }); + + keyInput->AddKeyPressListener([&](KeyboardEvent event) { + std::string keyInfo = std::format("

Key Press: Key='{}', Code={}, Ctrl={}, Shift={}, Alt={}

", + event.key, event.keyCode, event.ctrlKey, event.shiftKey, event.altKey); + keyOutput->SetInnerHTML(keyInfo); + }); + + // Focus Events + focusInput->AddFocusListener([&](FocusEvent event) { + focusOutput->SetInnerHTML("

Focus: Element gained focus

"); + }); + + focusInput->AddBlurListener([&](FocusEvent event) { + focusOutput->SetInnerHTML("

Blur: Element lost focus

"); + }); + + // Form Events + formInput->AddInputListener([&](InputEvent event) { + formOutput->SetInnerHTML(std::format("

Input: Value='{}'

", event.data)); + }); + + formInput->AddChangeListener([&](ChangeEvent event) { + formOutput->SetInnerHTML(std::format("

Change: Value='{}'

", event.value)); + }); + + formSelect->AddChangeListener([&](ChangeEvent event) { + formOutput->SetInnerHTML(std::format("

Select Change: Value='{}'

", event.value)); + }); + + // Window Events + // Resize event + body->AddResizeListener([&](ResizeEvent event) { + windowOutput->SetInnerHTML(std::format("

Resize: Width={}, Height={}

", event.width, event.height)); + }); + + // Scroll event + body->AddScrollListener([&](ScrollEvent event) { + windowOutput->SetInnerHTML(std::format("

Scroll: X={}, Y={}

", event.scrollX, event.scrollY)); + }); + + // Context Menu Event + body->AddContextMenuListener([&](MouseEvent event) { + windowOutput->SetInnerHTML(std::format("

Context Menu: X={}, Y={}

", event.clientX, event.clientY)); + }); + + // Drag and Drop Events + dragSource->AddDragStartListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drag Start: Dragging started

"); + }); + + dragSource->AddDragEndListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drag End: Dragging ended

"); + }); + + dropTarget->AddDragOverListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drag Over: Dragging over drop target

"); + }); + + dropTarget->AddDragEnterListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drag Enter: Drag entered drop target

"); + }); + + dropTarget->AddDragLeaveListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drag Leave: Drag left drop target

"); + }); + + dropTarget->AddDropListener([&](MouseEvent event) { + dragOutput->SetInnerHTML("

Drop: Item dropped

"); + }); + + // Wheel Event + wheelContainer->AddWheelListener([&](WheelEvent event) { + wheelOutput->SetInnerHTML(std::format("

Wheel: DeltaX={}, DeltaY={}, DeltaZ={}

", + event.deltaX, event.deltaY, event.deltaZ)); + }); + + return 0; +} \ No newline at end of file diff --git a/examples/EnhancedEventHandling/project.json b/examples/AllEventHandling/project.json similarity index 67% rename from examples/EnhancedEventHandling/project.json rename to examples/AllEventHandling/project.json index 9750e20..b2aedfb 100644 --- a/examples/EnhancedEventHandling/project.json +++ b/examples/AllEventHandling/project.json @@ -5,11 +5,11 @@ "name": "executable", "implementations": ["main"], "target": "wasm32-wasi", - "debug" : true, + "debug": true, "dependencies": [ { - "path":"../../project.json", - "configuration":"lib-debug" + "path": "../../project.json", + "configuration": "lib-debug" } ] } diff --git a/examples/EnhancedEventHandling/run.sh b/examples/AllEventHandling/run.sh similarity index 100% rename from examples/EnhancedEventHandling/run.sh rename to examples/AllEventHandling/run.sh diff --git a/examples/EnhancedEventHandling/main.cpp b/examples/EnhancedEventHandling/main.cpp deleted file mode 100644 index fb89730..0000000 --- a/examples/EnhancedEventHandling/main.cpp +++ /dev/null @@ -1,21 +0,0 @@ -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/InteractiveElement/main.cpp b/examples/InteractiveElement/main.cpp index f4c2d91..371ca9b 100644 --- a/examples/InteractiveElement/main.cpp +++ b/examples/InteractiveElement/main.cpp @@ -9,8 +9,8 @@ HtmlElement* button = new HtmlElement("myButton"); //prevent destruction int main() { - button->AddClickListener([](){ + button->AddClickListener([](Crafter::MouseEvent event){ auto output = HtmlElement("output"); - output.SetInnerHTML("Button was clicked!"); + output.SetInnerHTML("Button was clicked at (" + std::to_string(event.clientX) + ", " + std::to_string(event.clientY) + ")!"); }); } \ No newline at end of file diff --git a/interfaces/Crafter.CppDOM-BindingsExport.cppm b/interfaces/Crafter.CppDOM-BindingsExport.cppm index d9802e9..143f595 100644 --- a/interfaces/Crafter.CppDOM-BindingsExport.cppm +++ b/interfaces/Crafter.CppDOM-BindingsExport.cppm @@ -24,7 +24,7 @@ import :EventTypes; export namespace Crafter::CppDOMBindings { std::int32_t clickHandlerMaxId = 0; - std::unordered_map>* clickHandlers = new std::unordered_map>(); + std::unordered_map>* clickHandlers = new std::unordered_map>(); std::int32_t mouseOverHandlerMaxId = 0; std::unordered_map>* mouseOverHandlers = new std::unordered_map>(); @@ -106,8 +106,8 @@ extern "C" { std::free(ptr); } - __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(std::int32_t handlerID) { - Crafter::CppDOMBindings::clickHandlers->find(handlerID)->second(); + __attribute__((export_name("ExecuteClickHandler"))) void ExecuteClickHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, std::int32_t button, std::int32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { + Crafter::CppDOMBindings::clickHandlers->find(handlerID)->second(Crafter::MouseEvent(clientX, clientY, screenX, screenY, button, buttons, altKey, ctrlKey, shiftKey, metaKey)); } __attribute__((export_name("ExecuteMouseOverHandler"))) void ExecuteMouseOverHandler(std::int32_t handlerID, double clientX, double clientY, double screenX, double screenY, std::int32_t button, std::int32_t buttons, bool altKey, bool ctrlKey, bool shiftKey, bool metaKey) { diff --git a/interfaces/Crafter.CppDOM-HtmlElement.cppm b/interfaces/Crafter.CppDOM-HtmlElement.cppm index 09db530..fe93cb4 100644 --- a/interfaces/Crafter.CppDOM-HtmlElement.cppm +++ b/interfaces/Crafter.CppDOM-HtmlElement.cppm @@ -63,7 +63,7 @@ namespace Crafter { CppDOMBindings::SetInnerHTML(ptr, html); } - std::int32_t AddClickListener(std::function callback) { + std::int32_t AddClickListener(std::function callback) { std::int32_t id = CppDOMBindings::clickHandlerMaxId++; clickHandlers.push_back(id); CppDOMBindings::clickHandlers->insert({id, callback});