Added MenuBar
This commit is contained in:
parent
22ed3c0744
commit
d8e5b2e9be
11 changed files with 437 additions and 6 deletions
1
.clangd
1
.clangd
|
|
@ -1,4 +1,5 @@
|
|||
CompileFlags:
|
||||
CompilationDatabase: bin
|
||||
Add: ["--target=x86_64-w64-mingw32"]
|
||||
Diagnostics:
|
||||
MissingIncludes: None
|
||||
|
|
@ -85,6 +85,7 @@ list(APPEND OGFX_SOURCE_FILES
|
|||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WindowOutputHandler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/WidgetManager.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/ContextMenu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/MenuBar.cpp
|
||||
|
||||
# gui/widgets
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/ogfx/gui/widgets/Widget.cpp
|
||||
|
|
|
|||
|
|
@ -293,3 +293,18 @@ const $accentColorDark = #6B0A1DFF
|
|||
selectionGradient = gradientV(#C21135FF - #820B23FF)
|
||||
}
|
||||
% ==========================
|
||||
|
||||
|
||||
|
||||
% ====== MenuBar ======
|
||||
(menubar) {
|
||||
height = 24.0
|
||||
itemPadding = rect(0, 0, 15, 0)
|
||||
fontSize = 16
|
||||
backgroundColor = #CCAAAAFF
|
||||
textColor = $textColor
|
||||
selectionColor = $accentColor
|
||||
selectionTextColor = #FFFFFFFF
|
||||
borderColor = #400000FF
|
||||
}
|
||||
% =====================
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ Cache getStringDimensions() call in TabPanel::draw_tabs
|
|||
FIX: Optimize ListView
|
||||
FIX: Padding for ListView items
|
||||
Add icons to ListView
|
||||
FIX: Limit FPS even when continuous events happen
|
||||
|
||||
|
||||
|
||||
|
|
@ -57,15 +58,16 @@ Implement following widgets:
|
|||
***Vertical Slider
|
||||
***ListBox
|
||||
***Context Menu
|
||||
ComboBox
|
||||
Menu Bar
|
||||
***MenuBar
|
||||
Toolbar
|
||||
StatusBar
|
||||
ComboBox
|
||||
TreeView
|
||||
Layouts
|
||||
Vertical
|
||||
Horizontal
|
||||
Grid
|
||||
Fill
|
||||
Text Input
|
||||
TreeView
|
||||
Text Area
|
||||
Hex Editor
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
hide();
|
||||
// hide();
|
||||
event.handle();
|
||||
}
|
||||
|
||||
|
|
@ -244,6 +244,20 @@ namespace ogfx
|
|||
|
||||
void ContextMenu::onMousePressed(const Event& event)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
Vec2 mousePos { event.mouse->position_x, event.mouse->position_y };
|
||||
|
||||
for (i32 i = (i32)m_panels.size() - 1; i >= 0; --i)
|
||||
{
|
||||
i32 idx = entry_index_at(m_panels[i], mousePos);
|
||||
if (idx >= 0)
|
||||
{
|
||||
event.handle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hide();
|
||||
event.handle();
|
||||
}
|
||||
|
||||
|
|
|
|||
182
src/ogfx/gui/MenuBar.cpp
Normal file
182
src/ogfx/gui/MenuBar.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
#include "MenuBar.hpp"
|
||||
#include "../render/BasicRenderer.hpp"
|
||||
#include "Window.hpp"
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
MenuBar& MenuBar::create(void)
|
||||
{
|
||||
setSize(m_window.getWindowWidth(), m_height);
|
||||
setPosition(0, 0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MenuBar& MenuBar::addMenu(const String& label, const ContextMenu::Instance& instance)
|
||||
{
|
||||
m_slots.push_back({ label, instance, {} });
|
||||
recompute_layout();
|
||||
return *this;
|
||||
}
|
||||
|
||||
MenuBar& MenuBar::addMenu(const Menu& menu)
|
||||
{
|
||||
return addMenu(menu.label, menu.instance);
|
||||
}
|
||||
|
||||
void MenuBar::clearMenus(void)
|
||||
{
|
||||
close_menu();
|
||||
m_slots.clear();
|
||||
}
|
||||
|
||||
void MenuBar::onWindowResized(const Event& event)
|
||||
{
|
||||
setSize(m_window.getWindowWidth(), m_height);
|
||||
setPosition(0, 0);
|
||||
recompute_layout();
|
||||
}
|
||||
|
||||
void MenuBar::applyTheme(const ostd::Stylesheet& theme)
|
||||
{
|
||||
setHeight(theme.get<f32>("menubar.height", getHeight(), {}, {}));
|
||||
setItemPadding(theme.get<Rectangle>("menubar.itemPadding", getItemPadding(), {}, {}));
|
||||
setFontSize(theme.get<i32>("menubar.fontSize", getFontSize(), {}, {}));
|
||||
setBackgroundColor(theme.get<Color>("menubar.backgroundColor", getBackgroundColor(), {}, {}));
|
||||
setTextColor(theme.get<Color>("menubar.textColor", getTextColor(), {}, {}));
|
||||
setSelectionColor(theme.get<Color>("menubar.selectionColor", getSelectionColor(), {}, {}));
|
||||
setSelectionTextColor(theme.get<Color>("menubar.selectionTextColor", getSelectionTextColor(), {}, {}));
|
||||
setBorderColor(theme.get<Color>("menubar.borderColor", getBorderColor(), {}, {}));
|
||||
setSize(m_window.getWindowWidth(), m_height);
|
||||
recompute_layout();
|
||||
}
|
||||
|
||||
void MenuBar::recompute_layout(void)
|
||||
{
|
||||
auto& gfx = m_window.getGFX();
|
||||
f32 x = m_itemPadding.x;
|
||||
for (auto& slot : m_slots)
|
||||
{
|
||||
Vec2 textSize = gfx.getStringDimensions(slot.label, m_fontSize);
|
||||
f32 slotW = textSize.x + m_itemPadding.x + m_itemPadding.w;
|
||||
slot.rect = { x, 0, slotW, m_height };
|
||||
x += slotW;
|
||||
}
|
||||
}
|
||||
|
||||
i32 MenuBar::slot_index_at(const Vec2& mousePos) const
|
||||
{
|
||||
for (i32 i = 0; i < (i32)m_slots.size(); ++i)
|
||||
{
|
||||
if (m_slots[i].rect.contains(mousePos, true))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MenuBar::open_menu(i32 index)
|
||||
{
|
||||
if (index < 0 || index >= (i32)m_slots.size()) return;
|
||||
|
||||
const Slot& slot = m_slots[index];
|
||||
// Anchor menu just below the label
|
||||
Vec2 anchor { slot.rect.x, slot.rect.y + slot.rect.h };
|
||||
|
||||
m_window.setContextMenu(slot.instance);
|
||||
m_window.showContextMenu(anchor);
|
||||
|
||||
m_openIndex = index;
|
||||
m_active = true;
|
||||
}
|
||||
|
||||
void MenuBar::close_menu(void)
|
||||
{
|
||||
if (m_window.isContextMenuVisible())
|
||||
m_window.hideContextMenu();
|
||||
m_openIndex = -1;
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
void MenuBar::draw(BasicRenderer2D& gfx)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
|
||||
gfx.fillRect(*this, m_backgroundColor);
|
||||
|
||||
for (i32 i = 0; i < (i32)m_slots.size(); ++i)
|
||||
{
|
||||
const Slot& slot = m_slots[i];
|
||||
bool highlighted = (i == m_hoveredIndex) || (i == m_openIndex);
|
||||
|
||||
if (highlighted)
|
||||
{
|
||||
gfx.fillRect(slot.rect, m_selectionColor);
|
||||
gfx.drawCenteredString(slot.label, slot.rect, m_selectionTextColor, m_fontSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx.drawCenteredString(slot.label, slot.rect, m_textColor, m_fontSize);
|
||||
}
|
||||
}
|
||||
|
||||
// Bottom border line
|
||||
gfx.drawLine({ { getx(), gety() + m_height }, { getx() + getw(), gety() + m_height } }, m_borderColor);
|
||||
}
|
||||
|
||||
void MenuBar::update(void)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
|
||||
// If we're in active mode but the context menu got dismissed
|
||||
// (item clicked, click-outside, escape, etc.), drop out of active mode.
|
||||
if (m_active && !m_window.isContextMenuVisible())
|
||||
{
|
||||
m_openIndex = -1;
|
||||
m_active = false;
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::onMousePressed(const Event& event)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
|
||||
Vec2 mousePos { event.mouse->position_x, event.mouse->position_y };
|
||||
i32 idx = slot_index_at(mousePos);
|
||||
|
||||
if (idx < 0)
|
||||
{
|
||||
// Press outside the bar — let the context menu's own click-outside
|
||||
// handling close it; we'll catch up via update().
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_openIndex == idx)
|
||||
{
|
||||
// Clicking the open menu's own label closes it (toggle).
|
||||
close_menu();
|
||||
}
|
||||
else
|
||||
{
|
||||
open_menu(idx);
|
||||
}
|
||||
event.handle();
|
||||
}
|
||||
|
||||
void MenuBar::onMouseMoved(const Event& event)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
|
||||
Vec2 mousePos { event.mouse->position_x, event.mouse->position_y };
|
||||
m_hoveredIndex = slot_index_at(mousePos);
|
||||
|
||||
// Hover-switching: in active mode, moving onto a different label
|
||||
// instantly switches the open menu.
|
||||
if (m_active && m_hoveredIndex >= 0 && m_hoveredIndex != m_openIndex)
|
||||
{
|
||||
open_menu(m_hoveredIndex);
|
||||
event.handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
79
src/ogfx/gui/MenuBar.hpp
Normal file
79
src/ogfx/gui/MenuBar.hpp
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include <ogfx/gui/widgets/Widget.hpp>
|
||||
#include <ogfx/gui/ContextMenu.hpp>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
namespace gui
|
||||
{
|
||||
class Window;
|
||||
class MenuBar : public Rectangle
|
||||
{
|
||||
public: struct Menu
|
||||
{
|
||||
String label;
|
||||
ContextMenu::Instance instance;
|
||||
};
|
||||
|
||||
public:
|
||||
inline MenuBar(Window& window) : m_window(window) { create(); }
|
||||
MenuBar& create(void);
|
||||
MenuBar& addMenu(const String& label, const ContextMenu::Instance& instance);
|
||||
MenuBar& addMenu(const Menu& menu);
|
||||
void clearMenus(void);
|
||||
|
||||
void onWindowResized(const Event& event);
|
||||
void applyTheme(const ostd::Stylesheet& theme);
|
||||
void draw(BasicRenderer2D& gfx);
|
||||
void update(void);
|
||||
void onMousePressed(const Event& event);
|
||||
void onMouseMoved(const Event& event);
|
||||
|
||||
inline bool isVisible(void) const { return m_visible; }
|
||||
inline void show(bool v = true) { m_visible = v; }
|
||||
inline void hide(void) { show(false); m_active = false; m_openIndex = -1; }
|
||||
inline bool isActive(void) const { return m_active; }
|
||||
|
||||
OSTD_PARAM_GETSET(f32, Height, m_height);
|
||||
OSTD_PARAM_GETSET(Rectangle, ItemPadding, m_itemPadding);
|
||||
OSTD_PARAM_GETSET(i32, FontSize, m_fontSize);
|
||||
OSTD_PARAM_GETSET(Color, BackgroundColor, m_backgroundColor);
|
||||
OSTD_PARAM_GETSET(Color, TextColor, m_textColor);
|
||||
OSTD_PARAM_GETSET(Color, SelectionColor, m_selectionColor);
|
||||
OSTD_PARAM_GETSET(Color, SelectionTextColor, m_selectionTextColor);
|
||||
OSTD_PARAM_GETSET(Color, BorderColor, m_borderColor);
|
||||
|
||||
private:
|
||||
struct Slot
|
||||
{
|
||||
String label;
|
||||
ContextMenu::Instance instance;
|
||||
Rectangle rect; // screen-space, recomputed on layout
|
||||
};
|
||||
|
||||
void recompute_layout(void);
|
||||
i32 slot_index_at(const Vec2& mousePos) const;
|
||||
void open_menu(i32 index);
|
||||
void close_menu(void);
|
||||
|
||||
private:
|
||||
Window& m_window;
|
||||
stdvec<Slot> m_slots;
|
||||
|
||||
i32 m_openIndex { -1 };
|
||||
i32 m_hoveredIndex { -1 };
|
||||
bool m_active { false };
|
||||
bool m_visible { true };
|
||||
|
||||
f32 m_height { 26 };
|
||||
Rectangle m_itemPadding { 12, 0, 12, 0 }; // x = left, y = top, w = right, h = bottom
|
||||
i32 m_fontSize { 16 };
|
||||
Color m_backgroundColor { "#6B0A1DFF" };
|
||||
Color m_textColor { "#F16A85FF" };
|
||||
Color m_selectionColor { "#DC143CFF" };
|
||||
Color m_selectionTextColor { "#F16A85FF" };
|
||||
Color m_borderColor { "#400000FF" };
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -830,6 +830,7 @@ namespace ogfx
|
|||
m_rootWidget.__applyTheme(theme, true);
|
||||
m_rootWidget.reloadTheme(true);
|
||||
m_cmenu.applyTheme(theme);
|
||||
m_menubar.applyTheme(theme);
|
||||
}
|
||||
|
||||
void Window::__on_window_init(i32 width, i32 height, const String& title)
|
||||
|
|
@ -871,6 +872,8 @@ namespace ogfx
|
|||
m_rootWidget.__update();
|
||||
m_rootWidget.__draw(m_gfx);
|
||||
onRedraw(m_gfx);
|
||||
if (m_menubar.isVisible())
|
||||
m_menubar.draw(m_gfx);
|
||||
if (m_cmenu.isVisible())
|
||||
{
|
||||
stopTooltipTimer();
|
||||
|
|
@ -934,12 +937,16 @@ namespace ogfx
|
|||
m_cmenu.hide();
|
||||
evt.windowResized = &(ogfx::WindowResizedData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::WindowResized;
|
||||
if (m_menubar.isVisible())
|
||||
m_menubar.onWindowResized(evt);
|
||||
m_rootWidget.__onWindowResized(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::MouseMoved)
|
||||
{
|
||||
evt.mouse = &(ogfx::MouseEventData&)signal.userData;
|
||||
evt.__original_signal_id = ostd::BuiltinSignals::MouseMoved;
|
||||
if (m_menubar.isVisible())
|
||||
m_menubar.onMouseMoved(evt);
|
||||
if (m_cmenu.isVisible())
|
||||
m_cmenu.onMouseMoved(evt);
|
||||
m_rootWidget.__onMouseMoved(evt);
|
||||
|
|
@ -958,6 +965,8 @@ namespace ogfx
|
|||
evt.__original_signal_id = ostd::BuiltinSignals::MousePressed;
|
||||
if (m_cmenu.isVisible())
|
||||
m_cmenu.onMousePressed(evt);
|
||||
if (m_menubar.isVisible())
|
||||
m_menubar.onMousePressed(evt);
|
||||
m_rootWidget.__onMousePressed(evt);
|
||||
}
|
||||
else if (signal.ID == ostd::BuiltinSignals::MouseReleased)
|
||||
|
|
@ -994,6 +1003,8 @@ namespace ogfx
|
|||
void Window::__on_update(f64 delta)
|
||||
{
|
||||
m_cmenu.update();
|
||||
if (m_menubar.isVisible())
|
||||
m_menubar.update();
|
||||
onUpdate(delta);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include <ogfx/render/BasicRenderer.hpp>
|
||||
#include <ogfx/gui/WindowOutputHandler.hpp>
|
||||
#include <ogfx/gui/ContextMenu.hpp>
|
||||
#include <ogfx/gui/MenuBar.hpp>
|
||||
|
||||
namespace ogfx
|
||||
{
|
||||
|
|
@ -272,6 +273,9 @@ namespace ogfx
|
|||
void setTheme(const ostd::Stylesheet& theme) override;
|
||||
inline void showContextMenu(const Vec2& pos) { m_cmenu.show(pos); }
|
||||
inline void setContextMenu(const ContextMenu::Instance& instance) { m_cmenu.setInstance(instance); }
|
||||
inline bool isContextMenuVisible(void) const { return m_cmenu.isVisible(); }
|
||||
inline void hideContextMenu(void) { m_cmenu.hide(); }
|
||||
inline MenuBar& getMenuBar(void) { return m_menubar; }
|
||||
|
||||
inline virtual void onInitialize(void) { }
|
||||
inline virtual void onDestroy(void) { }
|
||||
|
|
@ -297,6 +301,9 @@ namespace ogfx
|
|||
ostd::StepTimer m_fixedUpdateTimer;
|
||||
ostd::StepTimer::TimePoint m_lastFrameTime;
|
||||
ContextMenu m_cmenu { *this };
|
||||
MenuBar m_menubar { *this };
|
||||
|
||||
friend class widgets::RootWidget;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,12 @@ namespace ogfx
|
|||
|
||||
void RootWidget::onWindowResized(const Event& event)
|
||||
{
|
||||
setSize(cast<f32>(event.windowResized->new_width), cast<f32>(event.windowResized->new_height));
|
||||
Window& win = cast<Window&>(getWindow()); //TODO: Potentially unsage?
|
||||
f32 offset_y = 0;
|
||||
if (win.m_menubar.isVisible())
|
||||
offset_y += win.m_menubar.geth();
|
||||
sety(offset_y);
|
||||
setSize(cast<f32>(event.windowResized->new_width), cast<f32>(event.windowResized->new_height) - offset_y);
|
||||
}
|
||||
|
||||
void RootWidget::applyTheme(const ostd::Stylesheet& theme)
|
||||
|
|
|
|||
|
|
@ -189,6 +189,31 @@ class Window : public ogfx::gui::Window
|
|||
};
|
||||
|
||||
setContextMenu(m_menu);
|
||||
|
||||
auto onActivate = [this](const ogfx::gui::ContextMenu::Entry& e) {
|
||||
out().fg("cyan").p("[MenuBar] Activated: ").fg("yellow").p(e.text)
|
||||
.fg("cyan").p(" (id=").fg("green").p(e.id).fg("cyan").p(")").reset().nl();
|
||||
|
||||
switch (e.id)
|
||||
{
|
||||
case TestMenuId::File_Exit:
|
||||
close();
|
||||
break;
|
||||
// ... add real handlers as you build them out
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
fileMenu.onActivate = onActivate;
|
||||
editMenu.onActivate = onActivate;
|
||||
viewMenu.onActivate = onActivate;
|
||||
helpMenu.onActivate = onActivate;
|
||||
|
||||
getMenuBar().addMenu("File", fileMenu)
|
||||
.addMenu("Edit", editMenu)
|
||||
.addMenu("View", viewMenu)
|
||||
.addMenu("Help", helpMenu);
|
||||
}
|
||||
|
||||
inline void onSignal(ostd::Signal& signal) override
|
||||
|
|
@ -239,7 +264,7 @@ class Window : public ogfx::gui::Window
|
|||
ListView m_list { *this };
|
||||
Label m_drawCallsLbl { *this };
|
||||
|
||||
enum MenuId { New = 1, Open, Save, SaveAs, Exit, CopyRaw, CopyFormatted };
|
||||
enum MenuId : i32 { New = 1, Open, Save, SaveAs, Exit, CopyRaw, CopyFormatted };
|
||||
|
||||
ogfx::gui::ContextMenu::Instance m_menu { {
|
||||
{ "File", -1, {
|
||||
|
|
@ -258,6 +283,95 @@ class Window : public ogfx::gui::Window
|
|||
nullptr
|
||||
};
|
||||
|
||||
|
||||
|
||||
enum TestMenuId : i32
|
||||
{
|
||||
// File
|
||||
File_New = 1,
|
||||
File_Open,
|
||||
File_OpenRecent_Project1,
|
||||
File_OpenRecent_Project2,
|
||||
File_OpenRecent_Project3,
|
||||
File_OpenRecent_ClearList,
|
||||
File_Save,
|
||||
File_SaveAs,
|
||||
File_Export_PNG,
|
||||
File_Export_JPG,
|
||||
File_Export_SVG,
|
||||
File_Export_PDF,
|
||||
File_Exit,
|
||||
|
||||
// Edit
|
||||
Edit_Undo,
|
||||
Edit_Redo,
|
||||
Edit_Cut,
|
||||
Edit_Copy,
|
||||
Edit_Paste,
|
||||
Edit_SelectAll,
|
||||
|
||||
// View
|
||||
View_ZoomIn,
|
||||
View_ZoomOut,
|
||||
View_ZoomReset,
|
||||
View_Theme_Dark,
|
||||
View_Theme_Light,
|
||||
View_Theme_Crimson,
|
||||
|
||||
// Help
|
||||
Help_Documentation,
|
||||
Help_About,
|
||||
};
|
||||
|
||||
ogfx::gui::ContextMenu::Instance fileMenu { {
|
||||
{ "New", TestMenuId::File_New },
|
||||
{ "Open...", TestMenuId::File_Open },
|
||||
{ "Open Recent", {
|
||||
{ "Project1.proj", TestMenuId::File_OpenRecent_Project1 },
|
||||
{ "Project2.proj", TestMenuId::File_OpenRecent_Project2 },
|
||||
{ "Project3.proj", TestMenuId::File_OpenRecent_Project3 },
|
||||
{ "Clear Recent List", TestMenuId::File_OpenRecent_ClearList },
|
||||
}},
|
||||
{ "Save", TestMenuId::File_Save },
|
||||
{ "Save As...",TestMenuId::File_SaveAs },
|
||||
{ "Export As", {
|
||||
{ "PNG Image", TestMenuId::File_Export_PNG },
|
||||
{ "JPG Image", TestMenuId::File_Export_JPG },
|
||||
{ "SVG Vector",TestMenuId::File_Export_SVG },
|
||||
{ "PDF Document", TestMenuId::File_Export_PDF },
|
||||
}},
|
||||
{ "Exit", TestMenuId::File_Exit } },
|
||||
nullptr
|
||||
};
|
||||
|
||||
ogfx::gui::ContextMenu::Instance editMenu { {
|
||||
{ "Undo", TestMenuId::Edit_Undo },
|
||||
{ "Redo", TestMenuId::Edit_Redo },
|
||||
{ "Cut", TestMenuId::Edit_Cut },
|
||||
{ "Copy", TestMenuId::Edit_Copy },
|
||||
{ "Paste", TestMenuId::Edit_Paste },
|
||||
{ "Select All", TestMenuId::Edit_SelectAll } },
|
||||
nullptr
|
||||
};
|
||||
|
||||
ogfx::gui::ContextMenu::Instance viewMenu { {
|
||||
{ "Zoom In", TestMenuId::View_ZoomIn },
|
||||
{ "Zoom Out", TestMenuId::View_ZoomOut },
|
||||
{ "Reset Zoom", TestMenuId::View_ZoomReset },
|
||||
{ "Theme", {
|
||||
{ "Dark", TestMenuId::View_Theme_Dark },
|
||||
{ "Light", TestMenuId::View_Theme_Light },
|
||||
{ "Crimson", TestMenuId::View_Theme_Crimson },
|
||||
}} },
|
||||
nullptr
|
||||
};
|
||||
|
||||
ogfx::gui::ContextMenu::Instance helpMenu { {
|
||||
{ "Documentation", TestMenuId::Help_Documentation },
|
||||
{ "About", TestMenuId::Help_About } },
|
||||
nullptr
|
||||
};
|
||||
|
||||
ostd::StepTimer m_timer;
|
||||
ostd::AsyncJob<bool> m_progressJob;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue