Skip to content

Commit 89403d4

Browse files
committed
Refactored code for font handling, added menu popup system, and improved highlighting dialect support.
1 parent 6d68e58 commit 89403d4

File tree

11 files changed

+1127
-355
lines changed

11 files changed

+1127
-355
lines changed

external/rlguipp/rlguipp.cpp

Lines changed: 438 additions & 1 deletion
Large diffs are not rendered by default.

external/rlguipp/rlguipp.hpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,15 @@ extern "C" {
7979
#endif
8080
#endif // __GNUC__
8181

82+
#if defined(__APPLE__) && defined(__clang__)
83+
#pragma clang diagnostic push
84+
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
85+
#endif
8286
#include "raygui4.5.h"
8387
#include "rlgl.h"
88+
#if defined(__APPLE__) && defined(__clang__)
89+
#pragma clang diagnostic pop
90+
#endif
8491

8592
#pragma GCC diagnostic pop
8693
}
@@ -230,5 +237,205 @@ RLGUIPP_API void SetDefaultFileIcons(const std::unordered_map<std::string_view,
230237
RLGUIPP_API bool ModalFileDialog(FileDialogInfo& info, bool* isOpen);
231238
RLGUIPP_API bool IsSysKeyDown(); // If macOS same as "IsKeyDown(KEY_LEFT_SUPER) || IsKeyDown(KEY_RIGHT_SUPER)" else "IsKeyDown(KEY_LEFT_CONTROL) || IsKeyDown(KEY_RIGHT_CONTROL)"
232239

240+
namespace PopupMenu {
241+
242+
// ============================================================================
243+
// Configuration - adjust these to match your UI style
244+
// ============================================================================
245+
246+
struct Style {
247+
Color shadow = {0, 0, 0, 80};
248+
// Dimensions
249+
int itemHeight = 11;
250+
int itemPaddingX = 12;
251+
int itemPaddingRight = 6; // space for submenu arrow
252+
int menuPaddingY = 2;
253+
int minWidth = 64;
254+
int separatorHeight = 3;
255+
int borderWidth = 1;
256+
int shadowOffset = 4;
257+
int fontSize = 8;
258+
int submenuArrowOffset = 10;
259+
int iconWidth = 12; // reserved space for checkmarks/icons
260+
261+
// Behavior
262+
float submenuOpenDelay = 0.20f; // seconds before submenu opens on hover
263+
float submenuCloseDelay = 0.15f; // grace period when moving to submenu
264+
};
265+
266+
// ============================================================================
267+
// Menu Item
268+
// ============================================================================
269+
270+
struct Item {
271+
enum class Type { Action, Submenu, Separator, Toggle };
272+
273+
Type type = Type::Action;
274+
std::string label;
275+
std::string shortcut; // optional shortcut hint text (display only)
276+
std::function<void()> action;
277+
std::vector<Item> children;
278+
bool enabled = true;
279+
bool* toggleValue = nullptr; // for toggle items
280+
281+
// Check if this item has a submenu
282+
[[nodiscard]] bool hasSubmenu() const { return !children.empty(); }
283+
284+
// Check if this item can react (can be clicked)
285+
[[nodiscard]] bool canReact() const {
286+
return enabled && type != Type::Separator && !hasSubmenu();
287+
}
288+
};
289+
290+
// Convenience type alias
291+
using Menu = std::vector<Item>;
292+
293+
// ============================================================================
294+
// Factory functions for creating menu items
295+
// ============================================================================
296+
297+
inline Item Action(std::string label, std::function<void()> action, std::string shortcut = "") {
298+
return Item{
299+
.type = Item::Type::Action,
300+
.label = std::move(label),
301+
.shortcut = std::move(shortcut),
302+
.action = std::move(action),
303+
.children = {},
304+
.enabled = true,
305+
.toggleValue = nullptr
306+
};
307+
}
308+
309+
inline Item Submenu(std::string label, std::vector<Item> children) {
310+
return Item{
311+
.type = Item::Type::Submenu,
312+
.label = std::move(label),
313+
.shortcut = {},
314+
.action = nullptr,
315+
.children = std::move(children),
316+
.enabled = true,
317+
.toggleValue = nullptr
318+
};
319+
}
320+
321+
inline Item Separator() {
322+
return Item{
323+
.type = Item::Type::Separator,
324+
.label = {},
325+
.shortcut = {},
326+
.action = nullptr,
327+
.children = {},
328+
.enabled = true,
329+
.toggleValue = nullptr
330+
};
331+
}
332+
333+
inline Item Toggle(std::string label, bool* value, std::function<void()> on_change = nullptr, std::string shortcut = "") {
334+
return Item{
335+
.type = Item::Type::Toggle,
336+
.label = std::move(label),
337+
.shortcut = std::move(shortcut),
338+
.action = std::move(on_change),
339+
.children = {},
340+
.enabled = true,
341+
.toggleValue = value
342+
};
343+
}
344+
345+
inline Item Disabled(Item item) {
346+
item.enabled = false;
347+
return item;
348+
}
349+
350+
// ============================================================================
351+
// Internal: Open menu state
352+
// ============================================================================
353+
354+
namespace detail {
355+
356+
struct OpenMenu {
357+
Vector2 position{0, 0};
358+
Menu const* items = nullptr;
359+
int hoveredIndex = -1;
360+
float hoverTime = 0.0f;
361+
int width = 0; // cached calculated width
362+
};
363+
364+
} // namespace detail
365+
366+
// ============================================================================
367+
// Popup Menu System
368+
// ============================================================================
369+
370+
class System {
371+
public:
372+
Style style;
373+
374+
// Open a popup menu at the given position
375+
void open(Vector2 position, const Menu& menu);
376+
377+
// Close all menus
378+
void close();
379+
380+
// Check if any menu is currently open
381+
[[nodiscard]] bool isOpen() const;
382+
383+
[[nodiscard]] bool isMenuOpen(const Menu& menu) const;
384+
385+
// Update menu state - call once per frame
386+
// Returns true if a menu action was triggered this frame
387+
bool update(float dt);
388+
389+
// Draw menus - call after drawing your scene (menus draw on top)
390+
void render() const;
391+
392+
// Get the last triggered action's label (for debugging/logging)
393+
[[nodiscard]] std::optional<std::string> lastAction() const { return _lastTriggeredAction; }
394+
395+
private:
396+
std::vector<detail::OpenMenu> _menuChain;
397+
std::optional<std::string> _lastTriggeredAction;
398+
float _closeGraceTimer = 0.0f;
399+
int _closeGraceLevel = -1;
400+
401+
// Calculate bounds for a menu panel
402+
[[nodiscard]] Rectangle getMenuBounds(const detail::OpenMenu& menu) const;
403+
404+
// Calculate the width needed for a menu
405+
[[nodiscard]] int calculateMenuWidth(const Menu& items) const;
406+
407+
// Calculate the text width for gui font
408+
[[nodiscard]] int calculateTextWidth(const std::string& text) const;
409+
410+
// Calculate total height of a menu
411+
[[nodiscard]] int calculateMenuHeight(const Menu& items) const;
412+
413+
// Get item height (separators are shorter)
414+
[[nodiscard]] int getItemHeight(const Item& item) const;
415+
416+
// Get which item index is at a Y position within a menu, or -1
417+
[[nodiscard]] int getItemAtYPos(const detail::OpenMenu& menu, float y) const;
418+
419+
// Open a submenu for the given parent level and item index
420+
void openSubmenu(int parent_level, int item_index);
421+
422+
// Trigger an item's action
423+
void triggerItem(const Item& item);
424+
425+
// Draw a single menu panel
426+
void drawMenu(const detail::OpenMenu& menu) const;
427+
428+
// Draw a single item within a menu
429+
void drawItem(const Item& item, Rectangle bounds, bool hovered) const;
430+
};
431+
432+
RLGUIPP_API void open(Vector2 position, const Menu& menu);
433+
RLGUIPP_API void close();
434+
RLGUIPP_API bool isOpen();
435+
RLGUIPP_API bool isMenuOpen(const Menu& menu);
436+
437+
} // namespace PopupMenu
438+
439+
233440
} // namespace gui
234441

external/rlguipp/test/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ if(NOT EMSCRIPTEN)
22
add_executable(rlguipp_test rlguipp_test.cpp stylemanager.cpp stylemanager.hpp fs_impl.cpp)
33
target_link_libraries(rlguipp_test PUBLIC rlguipp fmt::fmt)
44
endif()
5+
6+
add_executable(rlguipp_menu rlguipp_menu.cpp stylemanager.cpp stylemanager.hpp fs_impl.cpp)
7+
target_link_libraries(rlguipp_menu PUBLIC rlguipp fmt::fmt)

0 commit comments

Comments
 (0)