Skip to content

Commit bcfd05f

Browse files
committed
Add UI positioning strategy and placement options
Introduces the Placement enum to geometry.h for specifying UI element placement relative to anchors, with detailed documentation. Adds PositioningStrategy class and implementation to support absolute, cursor-based, and rectangle-relative positioning for UI elements.
1 parent 43139e2 commit bcfd05f

File tree

3 files changed

+263
-0
lines changed

3 files changed

+263
-0
lines changed

src/foundation/geometry.h

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,99 @@ struct Rectangle {
2828
double height;
2929
};
3030

31+
/**
32+
* @brief Placement options for positioning UI elements relative to an anchor.
33+
*
34+
* Defines how a UI element (such as a menu, tooltip, or popover) should be
35+
* positioned relative to an anchor element or point. The placement consists
36+
* of a primary direction (top, right, bottom, left) and an optional alignment
37+
* (start, center, end).
38+
*
39+
* Primary directions:
40+
* - Top: Element appears above the anchor
41+
* - Right: Element appears to the right of the anchor
42+
* - Bottom: Element appears below the anchor
43+
* - Left: Element appears to the left of the anchor
44+
*
45+
* Alignments:
46+
* - Start: Element aligns to the start edge (left for horizontal, top for vertical)
47+
* - Center: Element centers along the anchor (default if not specified)
48+
* - End: Element aligns to the end edge (right for horizontal, bottom for vertical)
49+
*
50+
* @note Use with PositioningStrategy (defined in positioning_strategy.h) to
51+
* specify both where and how to position UI elements.
52+
*
53+
* @example
54+
* ```cpp
55+
* // Position menu below the button, aligned to the left
56+
* menu->Open(PositioningStrategy::Absolute(100, 100), Placement::BottomStart);
57+
*
58+
* // Position popover to the right, aligned to the top
59+
* popover->Open(PositioningStrategy::CursorPosition(), Placement::RightStart);
60+
* ```
61+
*
62+
* @see PositioningStrategy
63+
*/
64+
enum class Placement {
65+
/**
66+
* Position above the anchor, horizontally centered.
67+
*/
68+
Top,
69+
70+
/**
71+
* Position above the anchor, aligned to the start (left).
72+
*/
73+
TopStart,
74+
75+
/**
76+
* Position above the anchor, aligned to the end (right).
77+
*/
78+
TopEnd,
79+
80+
/**
81+
* Position to the right of the anchor, vertically centered.
82+
*/
83+
Right,
84+
85+
/**
86+
* Position to the right of the anchor, aligned to the start (top).
87+
*/
88+
RightStart,
89+
90+
/**
91+
* Position to the right of the anchor, aligned to the end (bottom).
92+
*/
93+
RightEnd,
94+
95+
/**
96+
* Position below the anchor, horizontally centered.
97+
*/
98+
Bottom,
99+
100+
/**
101+
* Position below the anchor, aligned to the start (left).
102+
*/
103+
BottomStart,
104+
105+
/**
106+
* Position below the anchor, aligned to the end (right).
107+
*/
108+
BottomEnd,
109+
110+
/**
111+
* Position to the left of the anchor, vertically centered.
112+
*/
113+
Left,
114+
115+
/**
116+
* Position to the left of the anchor, aligned to the start (top).
117+
*/
118+
LeftStart,
119+
120+
/**
121+
* Position to the left of the anchor, aligned to the end (bottom).
122+
*/
123+
LeftEnd
124+
};
125+
31126
} // namespace nativeapi
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "positioning_strategy.h"
2+
3+
namespace nativeapi {
4+
5+
PositioningStrategy::PositioningStrategy(Type type)
6+
: type_(type), absolute_position_{0, 0}, relative_rect_{0, 0, 0, 0}, relative_offset_{0, 0} {}
7+
8+
PositioningStrategy PositioningStrategy::Absolute(double x, double y) {
9+
PositioningStrategy strategy(Type::Absolute);
10+
strategy.absolute_position_ = {x, y};
11+
return strategy;
12+
}
13+
14+
PositioningStrategy PositioningStrategy::CursorPosition() {
15+
return PositioningStrategy(Type::CursorPosition);
16+
}
17+
18+
PositioningStrategy PositioningStrategy::Relative(const Rectangle& rect, const Point& offset) {
19+
PositioningStrategy strategy(Type::Relative);
20+
strategy.relative_rect_ = rect;
21+
strategy.relative_offset_ = offset;
22+
return strategy;
23+
}
24+
25+
} // namespace nativeapi
26+
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#pragma once
2+
#include "geometry.h"
3+
4+
namespace nativeapi {
5+
6+
/**
7+
* @brief Strategy for determining where to position UI elements.
8+
*
9+
* PositioningStrategy defines how to calculate the position for UI elements
10+
* such as menus, tooltips, or popovers. It supports various positioning modes:
11+
* - Absolute: Fixed screen coordinates
12+
* - CursorPosition: Current mouse cursor position
13+
* - Relative: Position relative to a rectangle
14+
*
15+
* @example
16+
* ```cpp
17+
* // Position menu at absolute screen coordinates
18+
* menu->Open(PositioningStrategy::Absolute(100, 200), Placement::Bottom);
19+
*
20+
* // Position menu at current mouse location
21+
* menu->Open(PositioningStrategy::CursorPosition(), Placement::BottomStart);
22+
*
23+
* // Position menu relative to a rectangle
24+
* Rectangle buttonRect = button->GetBounds();
25+
* menu->Open(PositioningStrategy::Relative(buttonRect, {0, 10}), Placement::Bottom);
26+
* ```
27+
*/
28+
class PositioningStrategy {
29+
public:
30+
/**
31+
* @brief Type of positioning strategy.
32+
*/
33+
enum class Type {
34+
/**
35+
* Position at fixed screen coordinates.
36+
*/
37+
Absolute,
38+
39+
/**
40+
* Position at current mouse cursor location.
41+
*/
42+
CursorPosition,
43+
44+
/**
45+
* Position relative to a rectangle.
46+
*/
47+
Relative
48+
};
49+
50+
/**
51+
* @brief Create a strategy for absolute positioning at fixed coordinates.
52+
*
53+
* @param x X-coordinate in screen space
54+
* @param y Y-coordinate in screen space
55+
* @return PositioningStrategy configured for absolute positioning
56+
*
57+
* @example
58+
* ```cpp
59+
* auto strategy = PositioningStrategy::Absolute(100, 200);
60+
* menu->Open(strategy, Placement::Bottom);
61+
* ```
62+
*/
63+
static PositioningStrategy Absolute(double x, double y);
64+
65+
/**
66+
* @brief Create a strategy for positioning at current mouse location.
67+
*
68+
* @return PositioningStrategy configured to use mouse cursor position
69+
*
70+
* @example
71+
* ```cpp
72+
* auto strategy = PositioningStrategy::CursorPosition();
73+
* contextMenu->Open(strategy, Placement::BottomStart);
74+
* ```
75+
*/
76+
static PositioningStrategy CursorPosition();
77+
78+
/**
79+
* @brief Create a strategy for positioning relative to a rectangle.
80+
*
81+
* @param rect Rectangle in screen coordinates to position relative to
82+
* @param offset Optional offset point to apply to the position (default: {0, 0})
83+
* @return PositioningStrategy configured for rectangle-relative positioning
84+
*
85+
* @example
86+
* ```cpp
87+
* Rectangle buttonRect = button->GetBounds();
88+
* // Position at bottom of button
89+
* auto strategy = PositioningStrategy::Relative(buttonRect);
90+
* menu->Open(strategy, Placement::Bottom);
91+
*
92+
* // Position at bottom of button with 10px offset
93+
* auto strategy2 = PositioningStrategy::Relative(buttonRect, {0, 10});
94+
* menu->Open(strategy2, Placement::Bottom);
95+
* ```
96+
*/
97+
static PositioningStrategy Relative(const Rectangle& rect, const Point& offset = {0, 0});
98+
99+
/**
100+
* @brief Get the type of this positioning strategy.
101+
*
102+
* @return The Type enum value indicating the strategy type
103+
*/
104+
Type GetType() const { return type_; }
105+
106+
/**
107+
* @brief Get the absolute position (for Absolute type).
108+
*
109+
* @return Point containing x,y coordinates
110+
* @note Only valid when GetType() == Type::Absolute
111+
*/
112+
Point GetAbsolutePosition() const { return absolute_position_; }
113+
114+
/**
115+
* @brief Get the relative rectangle (for Relative type).
116+
*
117+
* @return Rectangle in screen coordinates
118+
* @note Only valid when GetType() == Type::Relative
119+
*/
120+
Rectangle GetRelativeRectangle() const { return relative_rect_; }
121+
122+
/**
123+
* @brief Get the relative offset point (for Relative type).
124+
*
125+
* @return Point containing x,y relative offset
126+
* @note Only valid when GetType() == Type::Relative
127+
*/
128+
Point GetRelativeOffset() const { return relative_offset_; }
129+
130+
private:
131+
/**
132+
* @brief Private constructor - use static factory methods instead.
133+
*/
134+
PositioningStrategy(Type type);
135+
136+
Type type_;
137+
Point absolute_position_;
138+
Rectangle relative_rect_;
139+
Point relative_offset_;
140+
};
141+
142+
} // namespace nativeapi

0 commit comments

Comments
 (0)