Skip to content

Commit 8a53d95

Browse files
committed
Add placement support for context menu positioning
Introduces a Placement enum to specify how menus are positioned relative to an anchor, and updates native and Dart APIs to support passing placement options when opening context menus. Removes debug print from context menu region and updates bindings and menu logic to handle placement.
1 parent b3bd373 commit 8a53d95

5 files changed

Lines changed: 168 additions & 9 deletions

File tree

packages/cnativeapi/lib/src/bindings_generated.dart

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1331,23 +1331,30 @@ class CNativeApiBindings {
13311331
/// Open the menu as a context menu using the specified positioning strategy
13321332
/// @param menu The menu
13331333
/// @param strategy The positioning strategy determining where to display the menu
1334+
/// @param placement The placement option determining how the menu is positioned
1335+
/// relative to the reference point (default: NATIVE_PLACEMENT_BOTTOM_START)
13341336
/// @return true if menu was opened successfully, false otherwise
13351337
bool native_menu_open(
13361338
native_menu_t menu,
13371339
native_positioning_strategy_t strategy,
1340+
native_placement_t placement,
13381341
) {
1339-
return _native_menu_open(menu, strategy);
1342+
return _native_menu_open(menu, strategy, placement.value);
13401343
}
13411344

13421345
late final _native_menu_openPtr =
13431346
_lookup<
13441347
ffi.NativeFunction<
1345-
ffi.Bool Function(native_menu_t, native_positioning_strategy_t)
1348+
ffi.Bool Function(
1349+
native_menu_t,
1350+
native_positioning_strategy_t,
1351+
ffi.UnsignedInt,
1352+
)
13461353
>
13471354
>('native_menu_open');
13481355
late final _native_menu_open = _native_menu_openPtr
13491356
.asFunction<
1350-
bool Function(native_menu_t, native_positioning_strategy_t)
1357+
bool Function(native_menu_t, native_positioning_strategy_t, int)
13511358
>();
13521359

13531360
/// Close the menu if it's currently showing
@@ -1901,6 +1908,64 @@ final class native_rectangle_t extends ffi.Struct {
19011908
external double height;
19021909
}
19031910

1911+
/// Placement options for positioning UI elements relative to an anchor.
1912+
enum native_placement_t {
1913+
/// Position above the anchor, horizontally centered.
1914+
NATIVE_PLACEMENT_TOP(0),
1915+
1916+
/// Position above the anchor, aligned to the start (left).
1917+
NATIVE_PLACEMENT_TOP_START(1),
1918+
1919+
/// Position above the anchor, aligned to the end (right).
1920+
NATIVE_PLACEMENT_TOP_END(2),
1921+
1922+
/// Position to the right of the anchor, vertically centered.
1923+
NATIVE_PLACEMENT_RIGHT(3),
1924+
1925+
/// Position to the right of the anchor, aligned to the start (top).
1926+
NATIVE_PLACEMENT_RIGHT_START(4),
1927+
1928+
/// Position to the right of the anchor, aligned to the end (bottom).
1929+
NATIVE_PLACEMENT_RIGHT_END(5),
1930+
1931+
/// Position below the anchor, horizontally centered.
1932+
NATIVE_PLACEMENT_BOTTOM(6),
1933+
1934+
/// Position below the anchor, aligned to the start (left).
1935+
NATIVE_PLACEMENT_BOTTOM_START(7),
1936+
1937+
/// Position below the anchor, aligned to the end (right).
1938+
NATIVE_PLACEMENT_BOTTOM_END(8),
1939+
1940+
/// Position to the left of the anchor, vertically centered.
1941+
NATIVE_PLACEMENT_LEFT(9),
1942+
1943+
/// Position to the left of the anchor, aligned to the start (top).
1944+
NATIVE_PLACEMENT_LEFT_START(10),
1945+
1946+
/// Position to the left of the anchor, aligned to the end (bottom).
1947+
NATIVE_PLACEMENT_LEFT_END(11);
1948+
1949+
final int value;
1950+
const native_placement_t(this.value);
1951+
1952+
static native_placement_t fromValue(int value) => switch (value) {
1953+
0 => NATIVE_PLACEMENT_TOP,
1954+
1 => NATIVE_PLACEMENT_TOP_START,
1955+
2 => NATIVE_PLACEMENT_TOP_END,
1956+
3 => NATIVE_PLACEMENT_RIGHT,
1957+
4 => NATIVE_PLACEMENT_RIGHT_START,
1958+
5 => NATIVE_PLACEMENT_RIGHT_END,
1959+
6 => NATIVE_PLACEMENT_BOTTOM,
1960+
7 => NATIVE_PLACEMENT_BOTTOM_START,
1961+
8 => NATIVE_PLACEMENT_BOTTOM_END,
1962+
9 => NATIVE_PLACEMENT_LEFT,
1963+
10 => NATIVE_PLACEMENT_LEFT_START,
1964+
11 => NATIVE_PLACEMENT_LEFT_END,
1965+
_ => throw ArgumentError("Unknown value for native_placement_t: $value"),
1966+
};
1967+
}
1968+
19041969
/// @brief Application event types
19051970
enum native_application_event_type_t {
19061971
NATIVE_APPLICATION_EVENT_STARTED(0),
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,87 @@
11
export 'dart:ui' show Offset, Size, Rect;
2+
3+
import 'package:cnativeapi/cnativeapi.dart' show native_placement_t;
4+
5+
/// Placement options for positioning UI elements relative to an anchor.
6+
///
7+
/// Placement defines how a UI element (such as a menu or popover) should be
8+
/// positioned relative to a reference point or rectangle.
9+
///
10+
/// Example:
11+
/// ```dart
12+
/// // Position menu below the anchor, horizontally centered
13+
/// menu.open(strategy, Placement.bottom);
14+
///
15+
/// // Position menu below the anchor, aligned to the left
16+
/// menu.open(strategy, Placement.bottomStart);
17+
///
18+
/// // Position menu above the anchor, aligned to the right
19+
/// menu.open(strategy, Placement.topEnd);
20+
/// ```
21+
enum Placement {
22+
/// Position above the anchor, horizontally centered.
23+
top,
24+
25+
/// Position above the anchor, aligned to the start (left).
26+
topStart,
27+
28+
/// Position above the anchor, aligned to the end (right).
29+
topEnd,
30+
31+
/// Position to the right of the anchor, vertically centered.
32+
right,
33+
34+
/// Position to the right of the anchor, aligned to the start (top).
35+
rightStart,
36+
37+
/// Position to the right of the anchor, aligned to the end (bottom).
38+
rightEnd,
39+
40+
/// Position below the anchor, horizontally centered.
41+
bottom,
42+
43+
/// Position below the anchor, aligned to the start (left).
44+
bottomStart,
45+
46+
/// Position below the anchor, aligned to the end (right).
47+
bottomEnd,
48+
49+
/// Position to the left of the anchor, vertically centered.
50+
left,
51+
52+
/// Position to the left of the anchor, aligned to the start (top).
53+
leftStart,
54+
55+
/// Position to the left of the anchor, aligned to the end (bottom).
56+
leftEnd;
57+
58+
/// Convert this Placement to a native placement enum value.
59+
native_placement_t toNative() {
60+
switch (this) {
61+
case Placement.top:
62+
return native_placement_t.NATIVE_PLACEMENT_TOP;
63+
case Placement.topStart:
64+
return native_placement_t.NATIVE_PLACEMENT_TOP_START;
65+
case Placement.topEnd:
66+
return native_placement_t.NATIVE_PLACEMENT_TOP_END;
67+
case Placement.right:
68+
return native_placement_t.NATIVE_PLACEMENT_RIGHT;
69+
case Placement.rightStart:
70+
return native_placement_t.NATIVE_PLACEMENT_RIGHT_START;
71+
case Placement.rightEnd:
72+
return native_placement_t.NATIVE_PLACEMENT_RIGHT_END;
73+
case Placement.bottom:
74+
return native_placement_t.NATIVE_PLACEMENT_BOTTOM;
75+
case Placement.bottomStart:
76+
return native_placement_t.NATIVE_PLACEMENT_BOTTOM_START;
77+
case Placement.bottomEnd:
78+
return native_placement_t.NATIVE_PLACEMENT_BOTTOM_END;
79+
case Placement.left:
80+
return native_placement_t.NATIVE_PLACEMENT_LEFT;
81+
case Placement.leftStart:
82+
return native_placement_t.NATIVE_PLACEMENT_LEFT_START;
83+
case Placement.leftEnd:
84+
return native_placement_t.NATIVE_PLACEMENT_LEFT_END;
85+
}
86+
}
87+
}

packages/nativeapi/lib/src/menu.dart

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,13 +338,23 @@ class Menu
338338
/// // Open context menu relative to a button with offset
339339
/// final buttonRect = button.getBounds();
340340
/// menu.open(PositioningStrategy.relative(buttonRect, Offset(0, 10)));
341+
///
342+
/// // Open context menu with custom placement
343+
/// menu.open(strategy, Placement.topStart);
341344
/// ```
342-
bool open(PositioningStrategy strategy) {
345+
bool open(
346+
PositioningStrategy strategy, [
347+
Placement placement = Placement.bottomStart,
348+
]) {
343349
// Convert Dart strategy to native strategy
344350
final nativeStrategy = strategy.toNative();
345351

346-
// Open menu with native strategy
347-
final result = bindings.native_menu_open(_nativeHandle, nativeStrategy);
352+
// Open menu with native strategy and placement
353+
final result = bindings.native_menu_open(
354+
_nativeHandle,
355+
nativeStrategy,
356+
placement.toNative(),
357+
);
348358

349359
// Free the native strategy
350360
bindings.native_positioning_strategy_free(nativeStrategy);

packages/nativeapi/lib/src/widgets/context_menu_region.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class _ContextMenuRegionState extends State<ContextMenuRegion> {
2626
},
2727
onPointerUp: (event) {
2828
if (!_shouldReact) return;
29-
print('object ${event.position}');
30-
3129
widget.menu.open(
3230
PositioningStrategy.absolute(
3331
Offset(event.position.dx, event.position.dy),

0 commit comments

Comments
 (0)