Finished Context Menu
This commit is contained in:
parent
eb27fa42d1
commit
b38874c78a
7 changed files with 359 additions and 71 deletions
|
|
@ -289,5 +289,7 @@ const $accentColorDark = #6B0A1DFF
|
|||
textColor = $textColor
|
||||
submenuIndicatorColor = $accentColorDark
|
||||
borderColor = #400000FF
|
||||
useSelectionGradient = true
|
||||
selectionGradient = gradientV(#C21135FF - #820B23FF)
|
||||
}
|
||||
% ==========================
|
||||
|
|
|
|||
|
|
@ -56,13 +56,15 @@ Implement following widgets:
|
|||
***Horizontal Slider
|
||||
***Vertical Slider
|
||||
***ListBox
|
||||
***Context Menu
|
||||
ComboBox
|
||||
Context Menu
|
||||
Menu Bar
|
||||
Menu Bar
|
||||
Toolbar
|
||||
Layouts
|
||||
Vertical
|
||||
Horizontal
|
||||
Grid
|
||||
Fill
|
||||
Text Input
|
||||
TreeView
|
||||
Hex Editor
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
2073
|
||||
2074
|
||||
|
|
|
|||
|
|
@ -39,9 +39,12 @@ namespace ogfx
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ContextMenu& ContextMenu::create(void)
|
||||
{
|
||||
setSize(130, 300);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -57,64 +60,185 @@ namespace ogfx
|
|||
setTextColor(theme.get<Color>("context.textColor", getTextColor(), {}, {}));
|
||||
setSubmenuIndicatorColor(theme.get<Color>("context.submenuIndicatorColor", getSubmenuIndicatorColor(), {}, {}));
|
||||
setBorderColor(theme.get<Color>("context.borderColor", getBorderColor(), {}, {}));
|
||||
enableSelectionGradient(theme.get<bool>("context.useSelectionGradient", isSelectionGradientEnabled(), {}, {}));
|
||||
setSelectionGradient(theme.get<ColorGradient>("context.selectionGradient", getSelectionGradient(), {}, {}));
|
||||
}
|
||||
|
||||
void ContextMenu::draw(BasicRenderer2D& gfx)
|
||||
{
|
||||
gfx.fillRect(*this, getBackgroundColor());
|
||||
const f32 triPad = 14;
|
||||
f32 y = 0;
|
||||
i32 i = 0;
|
||||
for (auto& entry : m_data.entries)
|
||||
if (!m_visible) return;
|
||||
for (const auto& panel : m_panels)
|
||||
draw_panel(gfx, panel);
|
||||
}
|
||||
|
||||
void ContextMenu::update(void)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
|
||||
if (m_pendingOpenPanelDepth >= 0 && m_hoverOpenTimerActive && m_hoverOpenTimer.read() >= SubmenuOpenDelayMs)
|
||||
{
|
||||
Vec2 entryPos = getPosition() + Vec2 { m_padding.x, y + m_padding.y };
|
||||
Rectangle rect = { entryPos - Vec2 { m_padding.x, 0 }, getw(), m_entryHeight };
|
||||
if (rect.contains(m_mousePos, true))
|
||||
{
|
||||
gfx.outlinedRect(rect, getSelectionColor(), getSeparatorLineColor(), 1, false, false, i != m_data.entries.size() , false);
|
||||
gfx.drawVCenteredString(entry.text, { entryPos, getw(), m_entryHeight }, getSelectionTextColor(), getFontSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx.drawRect(rect, getSeparatorLineColor(), 1, false, false, i != m_data.entries.size() , false);
|
||||
gfx.drawVCenteredString(entry.text, { entryPos, getw(), m_entryHeight }, getTextColor(), getFontSize());
|
||||
}
|
||||
if (entry.submenus.size() > 0)
|
||||
{
|
||||
Triangle tri {
|
||||
{ rect.x + rect.w - m_entryHeight + triPad, rect.y + (triPad * 0.5f) },
|
||||
{ rect.x + rect.w - (triPad * 0.5f), rect.y + (rect.h * 0.5f) },
|
||||
{ rect.x + rect.w - m_entryHeight + triPad, rect.y + rect.h - (triPad * 0.5f) }
|
||||
};
|
||||
gfx.fillTriangle(tri, getSubmenuIndicatorColor());
|
||||
}
|
||||
y += m_entryHeight;
|
||||
i++;
|
||||
Panel& parent = m_panels[m_pendingOpenPanelDepth];
|
||||
i32 entryIdx = m_pendingOpenEntryIndex;
|
||||
Entry& e = (*parent.entries)[entryIdx];
|
||||
|
||||
pop_to_depth(m_pendingOpenPanelDepth);
|
||||
|
||||
Rectangle r = entry_rect(parent, entryIdx);
|
||||
Vec2 anchor { parent.position.x + parent.size.x, r.y };
|
||||
push_panel(e.submenus, anchor, false);
|
||||
m_panels[m_pendingOpenPanelDepth].openedSubmenuIndex = entryIdx;
|
||||
|
||||
m_hoverOpenTimer.endCount();
|
||||
m_hoverOpenTimerActive = false;
|
||||
m_pendingOpenPanelDepth = -1;
|
||||
m_pendingOpenEntryIndex = -1;
|
||||
}
|
||||
|
||||
if (m_hoverCloseTimerActive && m_hoverCloseTimer.read() >= SubmenuCloseDelayMs)
|
||||
{
|
||||
i32 keepDepth = -1;
|
||||
for (i32 i = 0; i < (i32)m_panels.size(); ++i)
|
||||
{
|
||||
Rectangle r { m_panels[i].position, m_panels[i].size };
|
||||
if (r.contains(m_mousePos, true)) keepDepth = i;
|
||||
}
|
||||
if (keepDepth >= 0)
|
||||
{
|
||||
pop_to_depth(keepDepth);
|
||||
m_panels[keepDepth].openedSubmenuIndex = -1;
|
||||
}
|
||||
m_hoverCloseTimer.endCount();
|
||||
m_hoverCloseTimerActive = false;
|
||||
}
|
||||
gfx.drawRect(*this, getBorderColor(), 2);
|
||||
}
|
||||
|
||||
void ContextMenu::onMouseReleased(const Event& event)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
Vec2 mousePos { event.mouse->position_x, event.mouse->position_y };
|
||||
if (contains(mousePos, true))
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
for (i32 i = (i32)m_panels.size() - 1; i >= 0; --i)
|
||||
{
|
||||
hide();
|
||||
i32 idx = entry_index_at(m_panels[i], mousePos);
|
||||
if (idx >= 0)
|
||||
{
|
||||
Entry& e = (*m_panels[i].entries)[idx];
|
||||
if (e.submenus.empty())
|
||||
{
|
||||
if (m_data.onActivate && e.id >= 0)
|
||||
m_data.onActivate(e);
|
||||
hide();
|
||||
event.handle();
|
||||
hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
pop_to_depth(i);
|
||||
Rectangle r = entry_rect(m_panels[i], idx);
|
||||
Vec2 anchor { m_panels[i].position.x + m_panels[i].size.x, r.y };
|
||||
push_panel(e.submenus, anchor, false);
|
||||
m_panels[i].openedSubmenuIndex = idx;
|
||||
}
|
||||
event.handle();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
hide();
|
||||
event.handle();
|
||||
}
|
||||
|
||||
void ContextMenu::onMouseMoved(const Event& event)
|
||||
{
|
||||
if (!m_visible) return;
|
||||
Vec2 mousePos { event.mouse->position_x, event.mouse->position_y };
|
||||
if (contains(mousePos, true))
|
||||
m_mousePos = mousePos;
|
||||
|
||||
i32 hitPanel = -1;
|
||||
i32 hitEntry = -1;
|
||||
for (i32 i = (i32)m_panels.size() - 1; i >= 0; --i)
|
||||
{
|
||||
m_mousePos = mousePos;
|
||||
i32 idx = entry_index_at(m_panels[i], mousePos);
|
||||
if (idx >= 0) { hitPanel = i; hitEntry = idx; break; }
|
||||
Rectangle panelRect { m_panels[i].position, m_panels[i].size };
|
||||
if (panelRect.contains(mousePos, true)) { hitPanel = i; hitEntry = -1; break; }
|
||||
}
|
||||
|
||||
for (i32 i = 0; i < (i32)m_panels.size(); ++i)
|
||||
m_panels[i].hoveredIndex = (i == hitPanel ? hitEntry : -1);
|
||||
|
||||
if (hitPanel < 0)
|
||||
{
|
||||
if (!m_hoverCloseTimerActive)
|
||||
{
|
||||
m_hoverCloseTimer.startCount(ostd::eTimeUnits::Milliseconds);
|
||||
m_hoverCloseTimerActive = true;
|
||||
}
|
||||
if (m_hoverOpenTimerActive)
|
||||
{
|
||||
m_hoverOpenTimer.endCount();
|
||||
m_hoverOpenTimerActive = false;
|
||||
}
|
||||
m_pendingOpenPanelDepth = -1;
|
||||
event.handle();
|
||||
return;
|
||||
}
|
||||
|
||||
if ((i32)m_panels.size() - 1 > hitPanel)
|
||||
{
|
||||
if (hitEntry != m_panels[hitPanel].openedSubmenuIndex)
|
||||
{
|
||||
if (!m_hoverCloseTimerActive)
|
||||
{
|
||||
m_hoverCloseTimer.startCount(ostd::eTimeUnits::Milliseconds);
|
||||
m_hoverCloseTimerActive = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hoverCloseTimerActive)
|
||||
{
|
||||
m_hoverCloseTimer.endCount();
|
||||
m_hoverCloseTimerActive = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hoverCloseTimerActive)
|
||||
{
|
||||
m_hoverCloseTimer.endCount();
|
||||
m_hoverCloseTimerActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hitEntry >= 0)
|
||||
{
|
||||
Entry& e = (*m_panels[hitPanel].entries)[hitEntry];
|
||||
bool hasChildren = e.submenus.size() > 0;
|
||||
bool alreadyOpen = (m_panels[hitPanel].openedSubmenuIndex == hitEntry) && ((i32)m_panels.size() - 1 > hitPanel);
|
||||
|
||||
if (hasChildren && !alreadyOpen)
|
||||
{
|
||||
if (m_pendingOpenPanelDepth != hitPanel || m_pendingOpenEntryIndex != hitEntry)
|
||||
{
|
||||
m_pendingOpenPanelDepth = hitPanel;
|
||||
m_pendingOpenEntryIndex = hitEntry;
|
||||
m_hoverOpenTimer.startCount(ostd::eTimeUnits::Milliseconds);
|
||||
m_hoverOpenTimerActive = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_hoverOpenTimerActive)
|
||||
{
|
||||
m_hoverOpenTimer.endCount();
|
||||
m_hoverOpenTimerActive = false;
|
||||
}
|
||||
m_pendingOpenPanelDepth = -1;
|
||||
}
|
||||
}
|
||||
|
||||
event.handle();
|
||||
}
|
||||
|
||||
|
|
@ -128,49 +252,163 @@ namespace ogfx
|
|||
event.handle();
|
||||
}
|
||||
|
||||
void ContextMenu::show(void)
|
||||
{
|
||||
m_visible = true;
|
||||
}
|
||||
|
||||
void ContextMenu::show(const Vec2& pos)
|
||||
{
|
||||
setPosition(pos);
|
||||
m_panels.clear();
|
||||
push_panel(m_data.entries, pos, false);
|
||||
m_visible = true;
|
||||
}
|
||||
|
||||
void ContextMenu::hide(void)
|
||||
{
|
||||
m_panels.clear();
|
||||
m_hoverOpenTimer.endCount();
|
||||
m_hoverCloseTimer.endCount();
|
||||
m_hoverOpenTimerActive = false;
|
||||
m_hoverCloseTimerActive = false;
|
||||
m_pendingOpenPanelDepth = -1;
|
||||
m_pendingOpenEntryIndex = -1;
|
||||
m_visible = false;
|
||||
}
|
||||
|
||||
void ContextMenu::setInstance(const Instance& instance)
|
||||
{
|
||||
m_data = instance;
|
||||
update_size();
|
||||
m_panels.clear();
|
||||
m_pendingOpenPanelDepth = -1;
|
||||
m_pendingOpenEntryIndex = -1;
|
||||
m_hoverOpenTimer.endCount();
|
||||
m_hoverCloseTimer.endCount();
|
||||
if (m_visible)
|
||||
push_panel(m_data.entries, getPosition(), false);
|
||||
}
|
||||
|
||||
void ContextMenu::setFontSize(i32 size)
|
||||
{
|
||||
m_fontSize = size;
|
||||
update_size();
|
||||
relayout_panels();
|
||||
}
|
||||
|
||||
void ContextMenu::update_size(void)
|
||||
void ContextMenu::push_panel(stdvec<Entry>& entries, const Vec2& anchorTopLeft, bool flipLeft)
|
||||
{
|
||||
setSize(0, 0);
|
||||
Panel p;
|
||||
p.entries = &entries;
|
||||
p.position = anchorTopLeft;
|
||||
compute_panel_size(p);
|
||||
|
||||
f32 windowW = (f32)m_window.getWindowWidth();
|
||||
f32 windowH = (f32)m_window.getWindowHeight();
|
||||
if (flipLeft && !m_panels.empty())
|
||||
{
|
||||
// anchorTopLeft was computed assuming "open right"; flip to open left
|
||||
p.position.x = m_panels.back().position.x - p.size.x;
|
||||
}
|
||||
else if (p.position.x + p.size.x > windowW && !m_panels.empty())
|
||||
{
|
||||
p.position.x = m_panels.back().position.x - p.size.x;
|
||||
}
|
||||
|
||||
if (p.position.y + p.size.y > windowH)
|
||||
p.position.y = windowH - p.size.y;
|
||||
if (p.position.y < 0) p.position.y = 0;
|
||||
if (p.position.x < 0) p.position.x = 0;
|
||||
|
||||
m_panels.push_back(p);
|
||||
}
|
||||
|
||||
void ContextMenu::compute_panel_size(Panel& panel)
|
||||
{
|
||||
panel.size = { 0, 0 };
|
||||
auto& gfx = m_window.getGFX();
|
||||
for (auto& entry : m_data.entries)
|
||||
for (auto& entry : *panel.entries)
|
||||
{
|
||||
auto s = gfx.getStringDimensions(entry.text, getFontSize());
|
||||
f32 extra = (entry.submenus.size() > 0 ? s.y : 0);
|
||||
if (s.x + extra > getw())
|
||||
setw(s.x + extra);
|
||||
addh(s.y + m_spacing);
|
||||
m_entryHeight = s.y + m_spacing;
|
||||
entry.update_size(gfx, getFontSize());
|
||||
if (s.x + extra > panel.size.x)
|
||||
panel.size.x = s.x + extra;
|
||||
panel.size.y += s.y + m_spacing;
|
||||
panel.entryHeight = s.y + m_spacing;
|
||||
}
|
||||
addSize({ m_padding.x + m_padding.w, m_padding.y + m_padding.h });
|
||||
panel.size.x += m_padding.x + m_padding.w;
|
||||
panel.size.y += m_padding.y + m_padding.h;
|
||||
}
|
||||
|
||||
void ContextMenu::pop_to_depth(size_t depth)
|
||||
{
|
||||
if (depth + 1 < m_panels.size())
|
||||
m_panels.resize(depth + 1);
|
||||
}
|
||||
|
||||
Rectangle ContextMenu::entry_rect(const Panel& panel, i32 index) const
|
||||
{
|
||||
return {
|
||||
panel.position.x,
|
||||
panel.position.y + m_padding.y + (index * panel.entryHeight),
|
||||
panel.size.x,
|
||||
panel.entryHeight
|
||||
};
|
||||
}
|
||||
|
||||
i32 ContextMenu::entry_index_at(const Panel& panel, const Vec2& mousePos) const
|
||||
{
|
||||
Rectangle panelRect { panel.position, panel.size };
|
||||
if (!panelRect.contains(mousePos, true)) return -1;
|
||||
for (i32 i = 0; i < (i32)panel.entries->size(); ++i)
|
||||
{
|
||||
if (entry_rect(panel, i).contains(mousePos, true))
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void ContextMenu::relayout_panels(void)
|
||||
{
|
||||
for (auto& panel : m_panels)
|
||||
compute_panel_size(panel);
|
||||
}
|
||||
|
||||
void ContextMenu::draw_panel(BasicRenderer2D& gfx, const Panel& panel)
|
||||
{
|
||||
gfx.fillRect({ panel.position, panel.size }, getBackgroundColor());
|
||||
const f32 triPad = 14;
|
||||
f32 y = 0;
|
||||
i32 i = 0;
|
||||
auto& entries = *panel.entries;
|
||||
for (auto& entry : entries)
|
||||
{
|
||||
Vec2 entryPos = panel.position + Vec2 { m_padding.x, y + m_padding.y };
|
||||
Rectangle rect = { entryPos - Vec2 { m_padding.x, 0 }, panel.size.x, panel.entryHeight };
|
||||
|
||||
bool highlighted = (panel.hoveredIndex == i)
|
||||
|| (panel.openedSubmenuIndex == i);
|
||||
|
||||
if (highlighted)
|
||||
{
|
||||
if (isSelectionGradientEnabled())
|
||||
gfx.fillGradientRect(rect, m_selectionGradient);
|
||||
else
|
||||
gfx.fillRect(rect, getSelectionColor());
|
||||
gfx.drawRect(rect, getSeparatorLineColor(), 1, false, false, i != entries.size() , false);
|
||||
gfx.drawVCenteredString(entry.text, { entryPos, panel.size.x, panel.entryHeight }, getSelectionTextColor(), getFontSize());
|
||||
}
|
||||
else
|
||||
{
|
||||
gfx.drawRect(rect, getSeparatorLineColor(), 1, false, false, i != entries.size() , false);
|
||||
gfx.drawVCenteredString(entry.text, { entryPos, panel.size.x, panel.entryHeight }, getTextColor(), getFontSize());
|
||||
}
|
||||
if (entry.submenus.size() > 0)
|
||||
{
|
||||
Triangle tri {
|
||||
{ rect.x + rect.w - panel.entryHeight + triPad, rect.y + (triPad * 0.5f) },
|
||||
{ rect.x + rect.w - (triPad * 0.5f), rect.y + (rect.h * 0.5f) },
|
||||
{ rect.x + rect.w - panel.entryHeight + triPad, rect.y + rect.h - (triPad * 0.5f) }
|
||||
};
|
||||
gfx.fillTriangle(tri, getSubmenuIndicatorColor());
|
||||
}
|
||||
y += panel.entryHeight;
|
||||
i++;
|
||||
}
|
||||
gfx.drawRect({ panel.position, panel.size }, getBorderColor(), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,30 +30,42 @@ namespace ogfx
|
|||
{
|
||||
public: struct Entry
|
||||
{
|
||||
inline Entry(const String& t, const stdvec<Entry>& sub = {}) { text = t; submenus = sub; }
|
||||
inline Entry(const String& t, i32 id = -1, const stdvec<Entry>& sub = {}) { text = t; this->id = id; submenus = sub; }
|
||||
inline Entry(const String& t, const stdvec<Entry>& sub) { text = t; id = -1; submenus = sub; }
|
||||
String text { "" };
|
||||
i32 id { -1 };
|
||||
stdvec<Entry> submenus;
|
||||
|
||||
private:
|
||||
Vec2 size;
|
||||
void update_size(BasicRenderer2D& gfx, i32 fontSize);
|
||||
|
||||
friend class ContextMenu;
|
||||
};
|
||||
public: struct Instance
|
||||
{
|
||||
using Callback = std::function<void(const Entry&)>;
|
||||
stdvec<Entry> entries;
|
||||
Callback onActivate { nullptr };
|
||||
};
|
||||
private: struct Panel
|
||||
{
|
||||
stdvec<Entry>* entries { nullptr };
|
||||
Vec2 position { 0, 0 };
|
||||
Vec2 size { 0, 0 };
|
||||
f32 entryHeight { 0 };
|
||||
i32 hoveredIndex { -1 };
|
||||
i32 openedSubmenuIndex { -1 };
|
||||
};
|
||||
public:
|
||||
inline ContextMenu(WindowCore& window) : m_window(window) { create(); }
|
||||
ContextMenu& create(void);
|
||||
void applyTheme(const ostd::Stylesheet& theme);
|
||||
void draw(BasicRenderer2D& gfx);
|
||||
void update(void);
|
||||
void onMouseReleased(const Event& event);
|
||||
void onMouseMoved(const Event& event);
|
||||
void onMousePressed(const Event& event);
|
||||
void onMouseScrolled(const Event& event);
|
||||
void show(void);
|
||||
void show(const Vec2& pos);
|
||||
void hide(void);
|
||||
void setInstance(const Instance& instance);
|
||||
|
|
@ -71,9 +83,17 @@ namespace ogfx
|
|||
OSTD_PARAM_GETSET(Color, TextColor, m_textColor);
|
||||
OSTD_PARAM_GETSET(Color, SubmenuIndicatorColor, m_submenuIndicatorColor);
|
||||
OSTD_PARAM_GETSET(Color, BorderColor, m_borderColor);
|
||||
OSTD_PARAM_GETSET(ColorGradient, SelectionGradient, m_selectionGradient);
|
||||
OSTD_BOOL_PARAM_GETSET_E(SelectionGradient, m_useSelectionGradient);
|
||||
|
||||
private:
|
||||
void update_size(void);
|
||||
void push_panel(stdvec<Entry>& entries, const Vec2& anchorTopLeft, bool flipLeft = false);
|
||||
void pop_to_depth(size_t depth);
|
||||
void compute_panel_size(Panel& panel);
|
||||
i32 entry_index_at(const Panel& panel, const Vec2& mousePos) const;
|
||||
Rectangle entry_rect(const Panel& panel, i32 index) const;
|
||||
void draw_panel(BasicRenderer2D& gfx, const Panel& panel);
|
||||
void relayout_panels(void);
|
||||
|
||||
private:
|
||||
WindowCore& m_window;
|
||||
|
|
@ -82,6 +102,15 @@ namespace ogfx
|
|||
f32 m_entryHeight { 0 };
|
||||
Vec2 m_mousePos { 0, 0 };
|
||||
|
||||
stdvec<Panel> m_panels;
|
||||
|
||||
i32 m_pendingOpenPanelDepth { -1 };
|
||||
i32 m_pendingOpenEntryIndex { -1 };
|
||||
ostd::Timer m_hoverOpenTimer;
|
||||
ostd::Timer m_hoverCloseTimer;
|
||||
bool m_hoverOpenTimerActive { false };
|
||||
bool m_hoverCloseTimerActive { false };
|
||||
|
||||
Rectangle m_padding { 16, 0, 16, 0 };
|
||||
f32 m_spacing { 8 };
|
||||
i32 m_fontSize { 18 };
|
||||
|
|
@ -92,8 +121,11 @@ namespace ogfx
|
|||
Color m_textColor { "#F16A85FF" };
|
||||
Color m_submenuIndicatorColor { "#111111FF" };
|
||||
Color m_borderColor { "#400000FF" };
|
||||
bool m_useSelectionGradient { true };
|
||||
ColorGradient m_selectionGradient { { "#C21135FF", "#820B23FF" }, { 1.0f } };
|
||||
|
||||
|
||||
static constexpr u64 SubmenuOpenDelayMs { 300 };
|
||||
static constexpr u64 SubmenuCloseDelayMs { 50 };
|
||||
friend class Instance;
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -993,6 +993,7 @@ namespace ogfx
|
|||
|
||||
void Window::__on_update(f64 delta)
|
||||
{
|
||||
m_cmenu.update();
|
||||
onUpdate(delta);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -183,6 +183,11 @@ class Window : public ogfx::gui::Window
|
|||
return true;
|
||||
});
|
||||
|
||||
|
||||
m_menu.onActivate = [this](const ogfx::gui::ContextMenu::Entry& e) {
|
||||
std::cout << e.text << " - " << (i32)e.id << "\n";
|
||||
};
|
||||
|
||||
setContextMenu(m_menu);
|
||||
}
|
||||
|
||||
|
|
@ -234,15 +239,23 @@ class Window : public ogfx::gui::Window
|
|||
ListView m_list { *this };
|
||||
Label m_drawCallsLbl { *this };
|
||||
|
||||
ogfx::gui::ContextMenu::Instance m_menu {
|
||||
{
|
||||
{ "Update" },
|
||||
{ "File" },
|
||||
{ "Open RAW", { { "Image" }, { "Text File" }, { "Audio" } } },
|
||||
{ "Mouse Settings", { { "Test" } } },
|
||||
{ "Terror" },
|
||||
{ "Properties" }
|
||||
}
|
||||
enum MenuId { New = 1, Open, Save, SaveAs, Exit, CopyRaw, CopyFormatted };
|
||||
|
||||
ogfx::gui::ContextMenu::Instance m_menu { {
|
||||
{ "File", -1, {
|
||||
{ "New", MenuId::New },
|
||||
{ "Open...", MenuId::Open },
|
||||
{ "Save", MenuId::Save },
|
||||
{ "Save As", MenuId::SaveAs },
|
||||
}},
|
||||
{ "Edit", -1, {
|
||||
{ "Copy", -1, {
|
||||
{ "As Text", MenuId::CopyRaw },
|
||||
{ "As HTML", MenuId::CopyFormatted },
|
||||
}},
|
||||
}},
|
||||
{ "Exit", MenuId::Exit } },
|
||||
nullptr
|
||||
};
|
||||
|
||||
ostd::StepTimer m_timer;
|
||||
|
|
|
|||
Loading…
Reference in a new issue