Skip to content

Commit db3dd06

Browse files
committed
Refactor native object access with NativeObjectProvider
Introduced NativeObjectProvider base class to standardize access to platform-specific native objects. Refactored Menu, MenuItem, and Window classes to inherit from NativeObjectProvider and moved platform-specific native object retrieval to GetNativeObjectInternal(). Updated all platform implementations to override GetNativeObjectInternal() instead of GetNativeObject().
1 parent 9990767 commit db3dd06

File tree

9 files changed

+129
-42
lines changed

9 files changed

+129
-42
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#pragma once
2+
3+
namespace nativeapi {
4+
5+
/**
6+
* @brief Base class that provides access to platform-specific native objects.
7+
*
8+
* This class provides a standardized way for cross-platform wrapper classes
9+
* to expose their underlying platform-specific objects. Similar to how
10+
* EventEmitter provides event-related functionality, NativeObjectProvider
11+
* provides native object access functionality.
12+
*
13+
* Classes that inherit from NativeObjectProvider can provide access to:
14+
* - NSWindow*, NSMenu*, NSMenuItem* on macOS
15+
* - HWND, HMENU on Windows
16+
* - GtkWidget*, GtkMenu* on Linux
17+
*
18+
* Example usage:
19+
*
20+
* class MyWidget : public NativeObjectProvider {
21+
* public:
22+
* MyWidget() : native_widget_(CreatePlatformWidget()) {}
23+
*
24+
* protected:
25+
* void* GetNativeObjectInternal() const override {
26+
* return native_widget_;
27+
* }
28+
*
29+
* private:
30+
* void* native_widget_;
31+
* };
32+
*
33+
* // Usage
34+
* MyWidget widget;
35+
* void* native = widget.GetNativeObject();
36+
*
37+
* #ifdef __APPLE__
38+
* NSView* nsview = (__bridge NSView*)native;
39+
* #elif defined(_WIN32)
40+
* HWND hwnd = (HWND)native;
41+
* #endif
42+
*/
43+
class NativeObjectProvider {
44+
public:
45+
/**
46+
* @brief Virtual destructor to ensure proper cleanup in derived classes.
47+
*/
48+
virtual ~NativeObjectProvider() = default;
49+
50+
/**
51+
* @brief Get the native platform-specific object.
52+
*
53+
* This method provides access to the underlying platform-specific
54+
* object for advanced use cases. Use with caution as this breaks
55+
* the abstraction layer.
56+
*
57+
* @return Pointer to the native object
58+
*
59+
* Platform-specific return types:
60+
* - macOS: NSWindow*, NSMenu*, NSMenuItem*, NSView*, etc.
61+
* - Windows: HWND, HMENU, etc.
62+
* - Linux: GtkWidget*, GtkMenu*, GdkWindow*, etc.
63+
*/
64+
void* GetNativeObject() const {
65+
return GetNativeObjectInternal();
66+
}
67+
68+
protected:
69+
/**
70+
* @brief Internal method to be implemented by derived classes.
71+
*
72+
* Derived classes must implement this method to return their
73+
* platform-specific native object.
74+
*
75+
* @return Pointer to the platform-specific native object
76+
*/
77+
virtual void* GetNativeObjectInternal() const = 0;
78+
};
79+
80+
} // namespace nativeapi

src/menu.h

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "event_emitter.h"
99
#include "geometry.h"
1010
#include "menu_event.h"
11+
#include "foundation/native_object_provider.h"
1112

1213
namespace nativeapi {
1314

@@ -156,20 +157,22 @@ class Menu;
156157
* auto item = MenuItem::Create("Open File", MenuItemType::Normal);
157158
* item->SetIcon("data:image/png;base64,...");
158159
* item->SetAccelerator(KeyboardAccelerator("O", KeyboardAccelerator::Ctrl));
159-
* item->AddListener<MenuItemClickedEvent>([](const MenuItemClickedEvent& event) {
160+
* item->AddListener<MenuItemClickedEvent>([](const MenuItemClickedEvent& event)
161+
* {
160162
* // Handle menu item click
161163
* std::cout << "Opening file..." << std::endl;
162164
* });
163165
*
164166
* // Create a checkbox item
165167
* auto checkbox = MenuItem::Create("Show Toolbar", MenuItemType::Checkbox);
166168
* checkbox->SetChecked(true);
167-
* checkbox->AddListener<MenuItemClickedEvent>([](const MenuItemClickedEvent& event) {
168-
* std::cout << "Toolbar clicked, handle state change manually" << std::endl;
169+
* checkbox->AddListener<MenuItemClickedEvent>([](const MenuItemClickedEvent&
170+
* event) { std::cout << "Toolbar clicked, handle state change manually" <<
171+
* std::endl;
169172
* });
170173
* ```
171174
*/
172-
class MenuItem : public EventEmitter {
175+
class MenuItem : public EventEmitter, public NativeObjectProvider {
173176
public:
174177
/**
175178
* @brief Factory method to create a new menu item.
@@ -435,7 +438,6 @@ class MenuItem : public EventEmitter {
435438
*/
436439
void RemoveSubmenu();
437440

438-
439441
/**
440442
* @brief Programmatically trigger this menu item.
441443
*
@@ -446,17 +448,6 @@ class MenuItem : public EventEmitter {
446448
*/
447449
bool Trigger();
448450

449-
/**
450-
* @brief Get the native platform-specific menu item object.
451-
*
452-
* This method provides access to the underlying platform-specific
453-
* menu item for advanced use cases. Use with caution as this breaks
454-
* the abstraction layer.
455-
*
456-
* @return Pointer to the native menu item object
457-
*/
458-
void* GetNativeObject() const;
459-
460451
/**
461452
* @brief Emit a menu item selected event.
462453
*
@@ -477,6 +468,17 @@ class MenuItem : public EventEmitter {
477468
*/
478469
void EmitStateChangedEvent(bool checked);
479470

471+
protected:
472+
/**
473+
* @brief Internal method to get the platform-specific native menu item object.
474+
*
475+
* This method must be implemented by platform-specific code to return
476+
* the underlying native menu item object.
477+
*
478+
* @return Pointer to the native menu item object
479+
*/
480+
void* GetNativeObjectInternal() const override;
481+
480482
private:
481483
friend class Menu;
482484

@@ -546,7 +548,7 @@ class MenuItem : public EventEmitter {
546548
* fileMenu->ShowAsContextMenu(100, 100);
547549
* ```
548550
*/
549-
class Menu : public EventEmitter {
551+
class Menu : public EventEmitter, public NativeObjectProvider {
550552
public:
551553
/**
552554
* @brief Factory method to create a new menu.
@@ -770,7 +772,6 @@ class Menu : public EventEmitter {
770772
*/
771773
bool IsEnabled() const;
772774

773-
774775
/**
775776
* @brief Create a standard menu item and add it to the menu.
776777
*
@@ -807,17 +808,6 @@ class Menu : public EventEmitter {
807808
std::shared_ptr<MenuItem> CreateAndAddSubmenu(const std::string& text,
808809
std::shared_ptr<Menu> submenu);
809810

810-
/**
811-
* @brief Get the native platform-specific menu object.
812-
*
813-
* This method provides access to the underlying platform-specific
814-
* menu for advanced use cases. Use with caution as this breaks
815-
* the abstraction layer.
816-
*
817-
* @return Pointer to the native menu object
818-
*/
819-
void* GetNativeObject() const;
820-
821811
/**
822812
* @brief Emit a menu opened event.
823813
*
@@ -834,6 +824,17 @@ class Menu : public EventEmitter {
834824
*/
835825
void EmitClosedEvent();
836826

827+
protected:
828+
/**
829+
* @brief Internal method to get the platform-specific native menu object.
830+
*
831+
* This method must be implemented by platform-specific code to return
832+
* the underlying native menu object.
833+
*
834+
* @return Pointer to the native menu object
835+
*/
836+
void* GetNativeObjectInternal() const override;
837+
837838
private:
838839
/**
839840
* @brief Private constructor for factory methods.

src/platform/linux/menu_linux.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ bool MenuItem::Trigger() {
210210
return false;
211211
}
212212

213-
void* MenuItem::GetNativeObject() const {
213+
void* MenuItem::GetNativeObjectInternal() const {
214214
return (void*)pimpl_->gtk_menu_item_;
215215
}
216216

@@ -430,7 +430,7 @@ std::shared_ptr<MenuItem> Menu::CreateAndAddSubmenu(const std::string& text, std
430430
return item;
431431
}
432432

433-
void* Menu::GetNativeObject() const {
433+
void* Menu::GetNativeObjectInternal() const {
434434
return (void*)pimpl_->gtk_menu_;
435435
}
436436

src/platform/linux/window_linux.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ void Window::StartResizing() {
347347
// Provide stub implementation
348348
}
349349

350-
void* Window::GetNativeObject() const {
350+
void* Window::GetNativeObjectInternal() const {
351351
return pimpl_ ? pimpl_->gdk_window_ : nullptr;
352352
}
353353

src/platform/macos/menu_macos.mm

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ - (void)menuDidClose:(NSMenu *)menu {
426426
return true;
427427
}
428428

429-
void* MenuItem::GetNativeObject() const {
429+
void* MenuItem::GetNativeObjectInternal() const {
430430
return (__bridge void*)pimpl_->ns_menu_item_;
431431
}
432432

@@ -688,7 +688,7 @@ - (void)menuDidClose:(NSMenu *)menu {
688688
return item;
689689
}
690690

691-
void* Menu::GetNativeObject() const {
691+
void* Menu::GetNativeObjectInternal() const {
692692
return (__bridge void*)pimpl_->ns_menu_;
693693
}
694694

src/platform/macos/window_macos.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@
326326

327327
void Window::StartResizing() {}
328328

329-
void* Window::GetNativeObject() const {
329+
void* Window::GetNativeObjectInternal() const {
330330
if (!pimpl_) {
331331
std::cout << "GetNativeObject: pimpl_ is null" << std::endl;
332332
return nullptr;

src/platform/windows/menu_windows.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ bool MenuItem::Trigger() {
296296
return true;
297297
}
298298

299-
void* MenuItem::GetNativeObject() const {
299+
void* MenuItem::GetNativeObjectInternal() const {
300300
return reinterpret_cast<void*>(static_cast<uintptr_t>(pimpl_->menu_item_id_));
301301
}
302302

@@ -565,7 +565,7 @@ std::shared_ptr<MenuItem> Menu::CreateAndAddSubmenu(const std::string& text, std
565565
return item;
566566
}
567567

568-
void* Menu::GetNativeObject() const {
568+
void* Menu::GetNativeObjectInternal() const {
569569
return pimpl_->hmenu_;
570570
}
571571

src/platform/windows/window_windows.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ void Window::StartResizing() {
486486
// This would require more complex implementation
487487
}
488488

489-
void* Window::GetNativeObject() const {
489+
void* Window::GetNativeObjectInternal() const {
490490
return pimpl_ ? reinterpret_cast<void*>(pimpl_->hwnd_) : nullptr;
491491
}
492492

src/window.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#pragma once
22
#include <string>
33
#include "geometry.h"
4+
#include "foundation/native_object_provider.h"
45

56
namespace nativeapi {
67

@@ -20,7 +21,7 @@ struct WindowOptions {
2021
/**
2122
* Window is a class that represents a window.
2223
*/
23-
class Window {
24+
class Window : public NativeObjectProvider {
2425
public:
2526
Window();
2627
Window(void* window);
@@ -86,11 +87,16 @@ class Window {
8687
void StartDragging();
8788
void StartResizing();
8889

90+
protected:
8991
/**
90-
* @brief Get the native window object for the current platform.
91-
* @return NSWindow* on macOS, HWND on Windows, GdkWindow* on Linux
92+
* @brief Internal method to get the platform-specific native window object.
93+
*
94+
* This method must be implemented by platform-specific code to return
95+
* the underlying native window object.
96+
*
97+
* @return Pointer to the native window object
9298
*/
93-
void* GetNativeObject() const;
99+
void* GetNativeObjectInternal() const override;
94100

95101
private:
96102
class Impl;

0 commit comments

Comments
 (0)