Skip to content

Commit 7de3fd6

Browse files
Copilotlijy91
andcommitted
Complete generic event system with integration examples and demo
Co-authored-by: lijy91 <3889523+lijy91@users.noreply.github.com>
1 parent 6d5ab15 commit 7de3fd6

File tree

8 files changed

+320
-1
lines changed

8 files changed

+320
-1
lines changed

.gitignore

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@
22
.vs/
33
.vscode/
44
build/
5-
cmake-build-debug/
5+
cmake-build-debug/
6+
7+
# Generated test binaries and object files
8+
*.o
9+
*_test
10+
callback_test
11+
simple_test
12+
event_test

src/callback_test

-194 KB
Binary file not shown.

src/complete_event_demo.cpp

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
#include "event_system.h"
2+
#include "common_events.h"
3+
#include "event_integration_example.h"
4+
#include <iostream>
5+
#include <thread>
6+
#include <chrono>
7+
8+
/**
9+
* Complete demonstration of the generic event system capabilities
10+
*/
11+
namespace nativeapi {
12+
13+
void DemonstrateGenericEventSystem() {
14+
std::cout << "=== Generic Event System Demonstration ===" << std::endl;
15+
16+
// Get global event dispatcher
17+
auto& dispatcher = GetGlobalEventDispatcher();
18+
19+
std::cout << "\n1. Setting up event listeners..." << std::endl;
20+
21+
// Example 1: Type-specific callback listeners
22+
auto key_listener = AddScopedListener<KeyPressedEvent>(dispatcher,
23+
[](const KeyPressedEvent& event) {
24+
std::cout << "🎹 Key pressed: " << event.GetKeycode() << std::endl;
25+
});
26+
27+
auto display_listener = AddScopedListener<DisplayAddedEvent>(dispatcher,
28+
[](const DisplayAddedEvent& event) {
29+
std::cout << "🖥️ Display added" << std::endl;
30+
});
31+
32+
// Example 2: Multi-event observer
33+
UnifiedSystemEventHandler system_handler;
34+
auto key_pressed_id = dispatcher.AddListener<KeyPressedEvent>(&system_handler);
35+
auto key_released_id = dispatcher.AddListener<KeyReleasedEvent>(&system_handler);
36+
auto display_added_id = dispatcher.AddListener<DisplayAddedEvent>(&system_handler);
37+
auto display_removed_id = dispatcher.AddListener<DisplayRemovedEvent>(&system_handler);
38+
auto app_started_id = dispatcher.AddListener<ApplicationStartedEvent>(&system_handler);
39+
40+
// Example 3: Application lifecycle listeners
41+
auto app_exit_listener = AddScopedListener<ApplicationExitingEvent>(dispatcher,
42+
[](const ApplicationExitingEvent& event) {
43+
std::cout << "🚪 Application exiting with code: " << event.GetExitCode() << std::endl;
44+
});
45+
46+
std::cout << "Total listeners registered: " << dispatcher.GetTotalListenerCount() << std::endl;
47+
48+
// Example 4: Start async processing
49+
std::cout << "\n2. Starting asynchronous event processing..." << std::endl;
50+
dispatcher.Start();
51+
52+
// Example 5: Synchronous event dispatch
53+
std::cout << "\n3. Dispatching synchronous events..." << std::endl;
54+
55+
dispatcher.DispatchSync<ApplicationStartedEvent>();
56+
57+
// Create dummy display for demonstration
58+
Display dummy_display; // Assuming Display has default constructor
59+
dispatcher.DispatchSync<DisplayAddedEvent>(dummy_display);
60+
61+
dispatcher.DispatchSync<KeyPressedEvent>(65); // 'A'
62+
dispatcher.DispatchSync<KeyReleasedEvent>(65);
63+
64+
// Example 6: Asynchronous event dispatch
65+
std::cout << "\n4. Dispatching asynchronous events..." << std::endl;
66+
67+
dispatcher.DispatchAsync<KeyPressedEvent>(66); // 'B'
68+
dispatcher.DispatchAsync<KeyPressedEvent>(67); // 'C'
69+
dispatcher.DispatchAsync<KeyReleasedEvent>(66);
70+
dispatcher.DispatchAsync<KeyReleasedEvent>(67);
71+
72+
dispatcher.DispatchAsync<DisplayRemovedEvent>(dummy_display);
73+
74+
// Wait for async events to process
75+
std::this_thread::sleep_for(std::chrono::milliseconds(100));
76+
77+
// Example 7: Custom event with complex data
78+
std::cout << "\n5. Custom complex event..." << std::endl;
79+
80+
class CustomUserEvent : public TypedEvent<CustomUserEvent> {
81+
public:
82+
CustomUserEvent(const std::string& action, int user_id, bool success)
83+
: action_(action), user_id_(user_id), success_(success) {}
84+
85+
const std::string& GetAction() const { return action_; }
86+
int GetUserId() const { return user_id_; }
87+
bool IsSuccess() const { return success_; }
88+
89+
private:
90+
std::string action_;
91+
int user_id_;
92+
bool success_;
93+
};
94+
95+
auto custom_listener = AddScopedListener<CustomUserEvent>(dispatcher,
96+
[](const CustomUserEvent& event) {
97+
std::cout << "👤 User " << event.GetUserId()
98+
<< " " << event.GetAction()
99+
<< " - " << (event.IsSuccess() ? "success" : "failed") << std::endl;
100+
});
101+
102+
dispatcher.DispatchSync<CustomUserEvent>("login", 123, true);
103+
dispatcher.DispatchAsync<CustomUserEvent>("logout", 123, true);
104+
105+
// Wait for final async event
106+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
107+
108+
// Example 8: Event timestamping
109+
std::cout << "\n6. Event timestamping demonstration..." << std::endl;
110+
111+
auto timestamp_listener = AddScopedListener<ApplicationExitingEvent>(dispatcher,
112+
[](const ApplicationExitingEvent& event) {
113+
auto now = std::chrono::steady_clock::now();
114+
auto event_time = event.GetTimestamp();
115+
auto diff = std::chrono::duration_cast<std::chrono::microseconds>(now - event_time);
116+
std::cout << "⏱️ Event processed " << diff.count() << " microseconds after creation" << std::endl;
117+
});
118+
119+
dispatcher.DispatchSync<ApplicationExitingEvent>(0);
120+
121+
// Example 9: Cleanup demonstration
122+
std::cout << "\n7. Cleanup and listener management..." << std::endl;
123+
124+
std::cout << "Listeners before cleanup: " << dispatcher.GetTotalListenerCount() << std::endl;
125+
126+
// Remove some specific listeners
127+
dispatcher.RemoveListener(key_pressed_id);
128+
dispatcher.RemoveListener(display_added_id);
129+
130+
std::cout << "Listeners after removing 2: " << dispatcher.GetTotalListenerCount() << std::endl;
131+
132+
// Scoped listeners will be automatically removed when they go out of scope
133+
134+
// Stop async processing
135+
std::cout << "\n8. Stopping async processing..." << std::endl;
136+
dispatcher.Stop();
137+
138+
std::cout << "\n=== Demonstration Complete ===" << std::endl;
139+
std::cout << "The generic event system provides:" << std::endl;
140+
std::cout << "✓ Type-safe event handling" << std::endl;
141+
std::cout << "✓ Both observer and callback patterns" << std::endl;
142+
std::cout << "✓ Synchronous and asynchronous dispatch" << std::endl;
143+
std::cout << "✓ Thread-safe operations" << std::endl;
144+
std::cout << "✓ Automatic memory management" << std::endl;
145+
std::cout << "✓ Event timestamping" << std::endl;
146+
std::cout << "✓ Exception safety" << std::endl;
147+
std::cout << "✓ RAII-based cleanup" << std::endl;
148+
149+
// Clean up remaining listeners
150+
dispatcher.RemoveListener(key_released_id);
151+
dispatcher.RemoveListener(display_removed_id);
152+
dispatcher.RemoveListener(app_started_id);
153+
154+
std::cout << "\nFinal listener count: " << dispatcher.GetTotalListenerCount() << std::endl;
155+
}
156+
157+
} // namespace nativeapi
158+
159+
#ifdef DEMO_MAIN
160+
int main() {
161+
nativeapi::DemonstrateGenericEventSystem();
162+
return 0;
163+
}
164+
#endif

src/event_dispatcher.o

-324 KB
Binary file not shown.

src/event_integration_example.h

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#pragma once
2+
3+
/**
4+
* Integration Example: Event-Aware Display Manager
5+
*
6+
* This example shows how to integrate the generic event system
7+
* with existing components like DisplayManager.
8+
*/
9+
10+
#include "display_manager.h"
11+
#include "event_system.h"
12+
#include "common_events.h"
13+
14+
namespace nativeapi {
15+
16+
/**
17+
* Extended DisplayManager that uses the generic event system
18+
* in addition to the existing listener pattern.
19+
*
20+
* This demonstrates how existing code can be enhanced with the
21+
* new event system without breaking existing functionality.
22+
*/
23+
class EventAwareDisplayManager : public DisplayManager {
24+
public:
25+
explicit EventAwareDisplayManager(EventDispatcher* dispatcher = nullptr)
26+
: dispatcher_(dispatcher ? dispatcher : &GetGlobalEventDispatcher()) {}
27+
28+
// Override methods to dispatch events
29+
void AddListener(DisplayListener* listener) override {
30+
DisplayManager::AddListener(listener);
31+
32+
// Also dispatch an event when listeners are added
33+
// This allows other parts of the system to react to listener changes
34+
if (dispatcher_) {
35+
// We could define a ListenerAddedEvent if needed
36+
}
37+
}
38+
39+
void RemoveListener(DisplayListener* listener) override {
40+
DisplayManager::RemoveListener(listener);
41+
42+
// Dispatch event for listener removal if needed
43+
}
44+
45+
protected:
46+
/**
47+
* Override the notification method to also dispatch generic events.
48+
* This is called internally when displays change.
49+
*/
50+
void NotifyListeners(std::function<void(DisplayListener*)> callback) override {
51+
// Call the base implementation first
52+
DisplayManager::NotifyListeners(callback);
53+
54+
// If this was a display added/removed notification, we could
55+
// dispatch the corresponding event here. For example:
56+
// dispatcher_->DispatchAsync<DisplayChangedEvent>(...);
57+
}
58+
59+
/**
60+
* Example method that would be called when a display is actually added.
61+
* This would normally be called by the platform-specific implementation.
62+
*/
63+
void OnSystemDisplayAdded(const Display& display) {
64+
// Update internal state
65+
// ... existing logic ...
66+
67+
// Notify existing listeners
68+
NotifyListeners([&display](DisplayListener* listener) {
69+
listener->OnDisplayAdded(display);
70+
});
71+
72+
// Dispatch generic event
73+
if (dispatcher_) {
74+
dispatcher_->DispatchAsync<DisplayAddedEvent>(display);
75+
}
76+
}
77+
78+
/**
79+
* Example method for display removal
80+
*/
81+
void OnSystemDisplayRemoved(const Display& display) {
82+
// Update internal state
83+
// ... existing logic ...
84+
85+
// Notify existing listeners
86+
NotifyListeners([&display](DisplayListener* listener) {
87+
listener->OnDisplayRemoved(display);
88+
});
89+
90+
// Dispatch generic event
91+
if (dispatcher_) {
92+
dispatcher_->DispatchAsync<DisplayRemovedEvent>(display);
93+
}
94+
}
95+
96+
private:
97+
EventDispatcher* dispatcher_;
98+
};
99+
100+
/**
101+
* Example of a unified event handler that can handle both
102+
* keyboard and display events using the generic event system.
103+
*/
104+
class UnifiedSystemEventHandler : public EventListener {
105+
public:
106+
void OnEvent(const Event& event) override {
107+
// Handle different event types
108+
if (auto display_added = dynamic_cast<const DisplayAddedEvent*>(&event)) {
109+
HandleDisplayAdded(*display_added);
110+
} else if (auto display_removed = dynamic_cast<const DisplayRemovedEvent*>(&event)) {
111+
HandleDisplayRemoved(*display_removed);
112+
} else if (auto key_pressed = dynamic_cast<const KeyPressedEvent*>(&event)) {
113+
HandleKeyPressed(*key_pressed);
114+
} else if (auto key_released = dynamic_cast<const KeyReleasedEvent*>(&event)) {
115+
HandleKeyReleased(*key_released);
116+
} else if (auto app_started = dynamic_cast<const ApplicationStartedEvent*>(&event)) {
117+
HandleApplicationStarted(*app_started);
118+
}
119+
}
120+
121+
private:
122+
void HandleDisplayAdded(const DisplayAddedEvent& event) {
123+
std::cout << "System: Display added" << std::endl;
124+
// Handle display addition...
125+
}
126+
127+
void HandleDisplayRemoved(const DisplayRemovedEvent& event) {
128+
std::cout << "System: Display removed" << std::endl;
129+
// Handle display removal...
130+
}
131+
132+
void HandleKeyPressed(const KeyPressedEvent& event) {
133+
std::cout << "System: Key " << event.GetKeycode() << " pressed" << std::endl;
134+
// Handle key press...
135+
}
136+
137+
void HandleKeyReleased(const KeyReleasedEvent& event) {
138+
std::cout << "System: Key " << event.GetKeycode() << " released" << std::endl;
139+
// Handle key release...
140+
}
141+
142+
void HandleApplicationStarted(const ApplicationStartedEvent& event) {
143+
std::cout << "System: Application started, setting up..." << std::endl;
144+
// Initialize system components...
145+
}
146+
};
147+
148+
} // namespace nativeapi

src/event_system.o

-3.45 KB
Binary file not shown.

src/event_test

-255 KB
Binary file not shown.

src/simple_test

-160 KB
Binary file not shown.

0 commit comments

Comments
 (0)