Skip to content

Commit 248a429

Browse files
committed
Refactor menu positioning to use PositioningStrategy
Replaces coordinate-based menu opening with a unified PositioningStrategy API across C, C++, and platform implementations. Adds C API bindings for positioning strategies, updates all usages to pass a strategy object, and removes legacy coordinate-based methods. This enables more flexible menu placement, including absolute, cursor, and relative positioning.
1 parent bcfd05f commit 248a429

File tree

19 files changed

+297
-233
lines changed

19 files changed

+297
-233
lines changed

examples/menu_c_example/main.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <string.h>
44
#include "../../src/capi/application_c.h"
55
#include "../../src/capi/menu_c.h"
6+
#include "../../src/capi/positioning_strategy_c.h"
67

78
// Event callback functions
89
void on_menu_item_clicked(const void* event, void* user_data) {
@@ -154,8 +155,9 @@ int main() {
154155
// Note: Programmatic event triggering is no longer available via trigger API.
155156
// Events can only be triggered through actual user interaction.
156157
printf("\n=== Programmatic Event Triggering Removed ===\n");
157-
printf("Note: The trigger API has been removed. Events are now only "
158-
"triggered through user interaction.\n");
158+
printf(
159+
"Note: The trigger API has been removed. Events are now only "
160+
"triggered through user interaction.\n");
159161

160162
// Demonstrate listener removal
161163
printf("\n=== Testing Listener Removal ===\n");
@@ -167,18 +169,22 @@ int main() {
167169
printf("Failed to remove checkbox click listener\n");
168170
}
169171

170-
printf("Checkbox item listener removed. Events will now only be triggered "
171-
"through user interaction.\n");
172+
printf(
173+
"Checkbox item listener removed. Events will now only be triggered "
174+
"through user interaction.\n");
172175

173176
// Open menu as context menu (this may not work in console applications)
174177
printf("\n=== Attempting to Open Context Menu ===\n");
175178
printf("Note: Context menu display may not work in console applications\n");
176179

177-
if (native_menu_open_at(menu, 100, 100)) {
180+
native_point_t point = {100, 100};
181+
native_positioning_strategy_t strategy = native_positioning_strategy_absolute(&point);
182+
if (native_menu_open(menu, strategy)) {
178183
printf("Context menu opened successfully\n");
179184
} else {
180185
printf("Failed to open context menu (expected in console app)\n");
181186
}
187+
native_positioning_strategy_free(strategy);
182188

183189
// Test additional functionality
184190
printf("\n=== Testing Additional Functionality ===\n");

examples/menu_example/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ int main() {
106106
std::cout << "Note: Context menu display may not work in console applications" << std::endl;
107107

108108
// Try to show at screen coordinates (100, 100)
109-
if (menu->Open(100, 100)) {
109+
if (menu->Open(PositioningStrategy::Absolute({100, 100}))) {
110110
std::cout << "Context menu opened successfully" << std::endl;
111111
} else {
112112
std::cout << "Failed to open context menu (expected in console app)" << std::endl;

src/capi/menu_c.cpp

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <map>
66
#include <memory>
77
#include <optional>
8+
#include "../foundation/positioning_strategy.h"
89
#include "../global_registry.h"
910
#include "../image.h"
1011
#include "../menu.h"
@@ -837,25 +838,14 @@ native_menu_item_list_t native_menu_get_all_items(native_menu_t menu) {
837838
}
838839
}
839840

840-
bool native_menu_open_at(native_menu_t menu, double x, double y) {
841-
if (!menu)
842-
return false;
843-
844-
try {
845-
auto menu_ptr = static_cast<Menu*>(menu);
846-
return menu_ptr->Open(x, y);
847-
} catch (...) {
848-
return false;
849-
}
850-
}
851-
852-
bool native_menu_open(native_menu_t menu) {
853-
if (!menu)
841+
bool native_menu_open(native_menu_t menu, native_positioning_strategy_t strategy) {
842+
if (!menu || !strategy)
854843
return false;
855844

856845
try {
857846
auto menu_ptr = static_cast<Menu*>(menu);
858-
return menu_ptr->Open();
847+
auto strategy_ptr = static_cast<PositioningStrategy*>(strategy);
848+
return menu_ptr->Open(*strategy_ptr);
859849
} catch (...) {
860850
return false;
861851
}
@@ -873,7 +863,6 @@ bool native_menu_close(native_menu_t menu) {
873863
}
874864
}
875865

876-
877866
// New menu event listener API implementation
878867
int native_menu_add_listener(native_menu_t menu,
879868
native_menu_event_type_t event_type,

src/capi/menu_c.h

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern "C" {
1616

1717
#include "geometry_c.h"
1818
#include "image_c.h"
19+
#include "positioning_strategy_c.h"
1920

2021
/**
2122
* Opaque handles for menu objects
@@ -473,22 +474,13 @@ FFI_PLUGIN_EXPORT
473474
native_menu_item_list_t native_menu_get_all_items(native_menu_t menu);
474475

475476
/**
476-
* Open the menu as a context menu at specified coordinates
477+
* Open the menu as a context menu using the specified positioning strategy
477478
* @param menu The menu
478-
* @param x The x-coordinate in screen coordinates
479-
* @param y The y-coordinate in screen coordinates
479+
* @param strategy The positioning strategy determining where to display the menu
480480
* @return true if menu was opened successfully, false otherwise
481481
*/
482482
FFI_PLUGIN_EXPORT
483-
bool native_menu_open_at(native_menu_t menu, double x, double y);
484-
485-
/**
486-
* Open the menu as a context menu at default location
487-
* @param menu The menu
488-
* @return true if menu was opened successfully, false otherwise
489-
*/
490-
FFI_PLUGIN_EXPORT
491-
bool native_menu_open(native_menu_t menu);
483+
bool native_menu_open(native_menu_t menu, native_positioning_strategy_t strategy);
492484

493485
/**
494486
* Close the menu if it's currently showing
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#include "positioning_strategy_c.h"
2+
#include "../foundation/positioning_strategy.h"
3+
4+
using namespace nativeapi;
5+
6+
extern "C" {
7+
8+
native_positioning_strategy_t native_positioning_strategy_absolute(const native_point_t* point) {
9+
if (!point) {
10+
return nullptr;
11+
}
12+
13+
Point cpp_point{point->x, point->y};
14+
PositioningStrategy* strategy = new PositioningStrategy(PositioningStrategy::Absolute(cpp_point));
15+
return static_cast<native_positioning_strategy_t>(strategy);
16+
}
17+
18+
native_positioning_strategy_t native_positioning_strategy_cursor_position() {
19+
PositioningStrategy* strategy = new PositioningStrategy(PositioningStrategy::CursorPosition());
20+
return static_cast<native_positioning_strategy_t>(strategy);
21+
}
22+
23+
native_positioning_strategy_t native_positioning_strategy_relative(const native_rectangle_t* rect,
24+
const native_point_t* offset) {
25+
if (!rect) {
26+
return nullptr;
27+
}
28+
29+
Rectangle cpp_rect{rect->x, rect->y, rect->width, rect->height};
30+
Point cpp_offset{0, 0};
31+
if (offset) {
32+
cpp_offset = Point{offset->x, offset->y};
33+
}
34+
35+
PositioningStrategy* strategy =
36+
new PositioningStrategy(PositioningStrategy::Relative(cpp_rect, cpp_offset));
37+
return static_cast<native_positioning_strategy_t>(strategy);
38+
}
39+
40+
void native_positioning_strategy_free(native_positioning_strategy_t strategy) {
41+
if (strategy) {
42+
delete static_cast<PositioningStrategy*>(strategy);
43+
}
44+
}
45+
46+
} // extern "C"

src/capi/positioning_strategy_c.h

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#pragma once
2+
3+
#include <stdbool.h>
4+
5+
#include "geometry_c.h"
6+
7+
#if _WIN32
8+
#define FFI_PLUGIN_EXPORT __declspec(dllexport)
9+
#else
10+
#define FFI_PLUGIN_EXPORT
11+
#endif
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
/**
18+
* Type of positioning strategy
19+
*/
20+
typedef enum {
21+
NATIVE_POSITIONING_ABSOLUTE,
22+
NATIVE_POSITIONING_CURSOR_POSITION,
23+
NATIVE_POSITIONING_RELATIVE
24+
} native_positioning_strategy_type_t;
25+
26+
/**
27+
* Opaque handle for positioning strategy
28+
*/
29+
typedef void* native_positioning_strategy_t;
30+
31+
/**
32+
* Create a positioning strategy for absolute positioning at fixed coordinates
33+
* @param point Point in screen coordinates
34+
* @return Positioning strategy handle
35+
*/
36+
FFI_PLUGIN_EXPORT
37+
native_positioning_strategy_t native_positioning_strategy_absolute(const native_point_t* point);
38+
39+
/**
40+
* Create a positioning strategy for positioning at current mouse location
41+
* @return Positioning strategy handle
42+
*/
43+
FFI_PLUGIN_EXPORT
44+
native_positioning_strategy_t native_positioning_strategy_cursor_position();
45+
46+
/**
47+
* Create a positioning strategy for positioning relative to a rectangle
48+
* @param rect Rectangle in screen coordinates to position relative to
49+
* @param offset Offset point to apply to the position, or NULL for no offset
50+
* @return Positioning strategy handle
51+
*
52+
* @example
53+
* ```c
54+
* native_rectangle_t buttonRect = {100, 100, 50, 30};
55+
* native_point_t offset = {0, 10};
56+
* native_positioning_strategy_t strategy = native_positioning_strategy_relative(&buttonRect,
57+
* &offset); native_menu_open(menu, strategy); native_positioning_strategy_free(strategy);
58+
* ```
59+
*/
60+
FFI_PLUGIN_EXPORT
61+
native_positioning_strategy_t native_positioning_strategy_relative(const native_rectangle_t* rect,
62+
const native_point_t* offset);
63+
64+
/**
65+
* Free a positioning strategy handle
66+
* @param strategy The positioning strategy to free
67+
*/
68+
FFI_PLUGIN_EXPORT
69+
void native_positioning_strategy_free(native_positioning_strategy_t strategy);
70+
71+
#ifdef __cplusplus
72+
}
73+
#endif

src/capi/tray_icon_c.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -376,18 +376,6 @@ bool native_tray_icon_remove_listener(native_tray_icon_t tray_icon, int listener
376376
}
377377
}
378378

379-
bool native_tray_icon_open_context_menu_at(native_tray_icon_t tray_icon, double x, double y) {
380-
if (!tray_icon)
381-
return false;
382-
383-
try {
384-
auto tray_icon_ptr = static_cast<TrayIcon*>(tray_icon);
385-
return tray_icon_ptr->OpenContextMenu(x, y);
386-
} catch (...) {
387-
return false;
388-
}
389-
}
390-
391379
bool native_tray_icon_open_context_menu(native_tray_icon_t tray_icon) {
392380
if (!tray_icon)
393381
return false;

src/capi/tray_icon_c.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -213,16 +213,6 @@ int native_tray_icon_add_listener(native_tray_icon_t tray_icon,
213213
FFI_PLUGIN_EXPORT
214214
bool native_tray_icon_remove_listener(native_tray_icon_t tray_icon, int listener_id);
215215

216-
/**
217-
* Open the context menu at specified coordinates
218-
* @param tray_icon The tray icon
219-
* @param x The x-coordinate in screen coordinates
220-
* @param y The y-coordinate in screen coordinates
221-
* @return true if menu was opened successfully, false otherwise
222-
*/
223-
FFI_PLUGIN_EXPORT
224-
bool native_tray_icon_open_context_menu_at(native_tray_icon_t tray_icon, double x, double y);
225-
226216
/**
227217
* Open the context menu at default location
228218
* @param tray_icon The tray icon

src/foundation/geometry.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ struct Rectangle {
5353
* @example
5454
* ```cpp
5555
* // Position menu below the button, aligned to the left
56-
* menu->Open(PositioningStrategy::Absolute(100, 100), Placement::BottomStart);
56+
* menu->Open(PositioningStrategy::Absolute({100, 100}), Placement::BottomStart);
5757
*
5858
* // Position popover to the right, aligned to the top
5959
* popover->Open(PositioningStrategy::CursorPosition(), Placement::RightStart);

src/foundation/positioning_strategy.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@ namespace nativeapi {
55
PositioningStrategy::PositioningStrategy(Type type)
66
: type_(type), absolute_position_{0, 0}, relative_rect_{0, 0, 0, 0}, relative_offset_{0, 0} {}
77

8-
PositioningStrategy PositioningStrategy::Absolute(double x, double y) {
8+
PositioningStrategy PositioningStrategy::Absolute(const Point& point) {
99
PositioningStrategy strategy(Type::Absolute);
10-
strategy.absolute_position_ = {x, y};
10+
strategy.absolute_position_ = point;
1111
return strategy;
1212
}
1313

@@ -23,4 +23,3 @@ PositioningStrategy PositioningStrategy::Relative(const Rectangle& rect, const P
2323
}
2424

2525
} // namespace nativeapi
26-

0 commit comments

Comments
 (0)