DIRECTORY: prepare to split the imgui logger from directory engine

other engines could use the same code, too and thus we will move this into the backend module
This commit is contained in:
Martin Gerhardy
2024-10-11 09:01:11 +02:00
parent 2a3d39edf7
commit 610384ed36
8 changed files with 283 additions and 235 deletions
+15
View File
@@ -66,4 +66,19 @@ void Palette(const Graphics::Palette &palette) {
drawList->Flags = backupFlags;
}
bool toggleButton(const char *label, bool *p_value, bool inverse) {
int pop = 0;
if (*p_value != inverse) {
ImVec4 hovered = ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered];
ImGui::PushStyleColor(ImGuiCol_Button, hovered);
pop = 1;
}
bool result = ImGui::Button(label);
if (result) {
*p_value = !*p_value;
}
ImGui::PopStyleColor(pop);
return result;
}
} // namespace ImGuiEx
+5
View File
@@ -21,6 +21,10 @@
#include "backends/imgui/IconsMaterialSymbols.h"
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "backends/imgui/imgui.h"
#include "graphics/palette.h"
@@ -38,5 +42,6 @@ bool InputInt(const char *label, INT *v, int step = 1, int step_fast = 100, ImGu
void Boolean(bool val);
void Palette(const Graphics::Palette &palette);
bool toggleButton(const char *label, bool *p_value, bool inverse = false);
} // namespace ImGuiEx
+1 -24
View File
@@ -39,21 +39,6 @@ namespace DT {
ImGuiState *_state = nullptr;
bool toggleButton(const char *label, bool *p_value, bool inverse) {
int pop = 0;
if (*p_value != inverse) {
ImVec4 hovered = ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered];
ImGui::PushStyleColor(ImGuiCol_Button, hovered);
pop = 1;
}
bool result = ImGui::Button(label);
if (result) {
*p_value = !*p_value;
}
ImGui::PopStyleColor(pop);
return result;
}
const LingoDec::Handler *getHandler(const Cast *cast, CastMemberID id, const Common::String &handlerId) {
if (!cast)
return nullptr;
@@ -283,15 +268,7 @@ static void showSettings() {
ImGui::ColorEdit4("Variable", &_state->_colors._var_ref.x);
ImGui::ColorEdit4("Variable changed", &_state->_colors._var_ref_changed.x);
ImGui::SeparatorText("Logger");
ImGui::ColorEdit4("Error", &_state->_colors._logger_error.x);
ImGui::ColorEdit4("Error Button", &_state->_colors._logger_error_b.x);
ImGui::ColorEdit4("Warning", &_state->_colors._logger_warning.x);
ImGui::ColorEdit4("Warning Button", &_state->_colors._logger_warning_b.x);
ImGui::ColorEdit4("Info", &_state->_colors._logger_info.x);
ImGui::ColorEdit4("Info Button", &_state->_colors._logger_info_b.x);
ImGui::ColorEdit4("Debug", &_state->_colors._logger_debug.x);
ImGui::ColorEdit4("Debug Button", &_state->_colors._logger_debug_b.x);
_state->_logger->drawColorOptions();
}
ImGui::End();
}
+3 -2
View File
@@ -20,6 +20,7 @@
*/
#include "backends/imgui/IconsMaterialSymbols.h"
#include "backends/imgui/imgui_utils.h"
#include "director/director.h"
#include "director/debugger/dt-internal.h"
@@ -114,10 +115,10 @@ void showCast() {
if (ImGui::Begin("Cast", &_state->_w.cast)) {
// display a toolbar with: grid/list/filters buttons + name filter
toggleButton(ICON_MS_LIST, &_state->_cast._listView);
ImGuiEx::toggleButton(ICON_MS_LIST, &_state->_cast._listView);
ImGui::SetItemTooltip("List");
ImGui::SameLine();
toggleButton(ICON_MS_GRID_VIEW, &_state->_cast._listView, true);
ImGuiEx::toggleButton(ICON_MS_GRID_VIEW, &_state->_cast._listView, true);
ImGui::SetItemTooltip("Grid");
ImGui::SameLine();
+3 -33
View File
@@ -22,7 +22,9 @@
#ifndef DIRECTOR_DEBUGER_DT_INTERNAL_H
#define DIRECTOR_DEBUGER_DT_INTERNAL_H
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "graphics/surface.h"
@@ -30,6 +32,7 @@
#include "backends/imgui/imgui_fonts.h"
#include "director/debugger/imgui_memory_editor.h"
#include "director/debugger/dt-logger.h"
#include "director/types.h"
#include "director/lingo/lingo.h"
@@ -137,16 +140,6 @@ typedef struct ImGuiState {
ImVec4 _script_ref = ImColor(IM_COL32(0x7f, 0x7f, 0xff, 0xfff));
ImVec4 _var_ref = ImColor(IM_COL32(0xe6, 0xe6, 0x00, 0xff));
ImVec4 _var_ref_changed = ImColor(IM_COL32(0xFF, 0x00, 0x00, 0xFF));
ImVec4 _logger_error_b = ImVec4(1.f, 0.f, 0.f, 1.f);
ImVec4 _logger_warning_b = ImVec4(1.f, 1.f, 0.f, 1.f);
ImVec4 _logger_info_b = ImVec4(1.f, 1.f, 1.f, 1.f);
ImVec4 _logger_debug_b = ImVec4(0.8f, 0.8f, 0.8f, 1.f);
ImVec4 _logger_error = ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
ImVec4 _logger_warning = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
ImVec4 _logger_info = ImVec4(1.0f, 0.8f, 0.6f, 1.0f);
ImVec4 _logger_debug = ImVec4(0.8f, 0.8f, 0.8f, 1.0f);
} _colors;
struct {
@@ -190,30 +183,7 @@ typedef struct ImGuiState {
ImGuiLogger *_logger = nullptr;
} ImGuiState;
// dt-logger.cpp
class ImGuiLogger {
char _inputBuf[256];
ImVector<char *> _items;
ImVector<char *> _history;
int _historyPos; // -1: new line, 0.._history.Size-1 browsing history.
ImGuiTextFilter _filter;
bool _autoScroll;
bool _scrollToBottom;
bool _showError = true;
bool _showWarn = true;
bool _showInfo = true;
bool _showdebug = true;
public:
ImGuiLogger();
~ImGuiLogger();
void clear();
void addLog(const char *fmt, ...) IM_FMTARGS(2);
void draw(const char *title, bool *p_open);
};
// debugtools.cpp
bool toggleButton(const char *label, bool *p_value, bool inverse = false);
ImGuiScript toImGuiScript(ScriptType scriptType, CastMemberID id, const Common::String &handlerId);
void setScriptToDisplay(const ImGuiScript &script);
Director::Breakpoint *getBreakpoint(const Common::String &handlerName, uint16 scriptId, uint pc);
+186 -174
View File
@@ -20,222 +20,234 @@
*/
#include "backends/imgui/IconsMaterialSymbols.h"
#include "common/debug.h"
#include "backends/imgui/imgui_utils.h"
#include "common/debug-channels.h"
#include "common/debug.h"
#include "director/director.h"
#include "director/debugger/dt-internal.h"
#include "director/debugger/dt-logger.h"
namespace Director {
namespace DT {
ImGuiLogger::ImGuiLogger() {
clear();
memset(_inputBuf, 0, sizeof(_inputBuf));
_historyPos = -1;
_autoScroll = true;
_scrollToBottom = false;
clear();
memset(_inputBuf, 0, sizeof(_inputBuf));
_historyPos = -1;
_autoScroll = true;
_scrollToBottom = false;
}
ImGuiLogger::~ImGuiLogger() {
clear();
for (int i = 0; i < _history.Size; i++)
free(_history[i]);
clear();
for (int i = 0; i < _history.Size; i++)
free(_history[i]);
}
void ImGuiLogger::clear() {
for (int i = 0; i < _items.Size; i++)
free(_items[i]);
_items.clear();
for (int i = 0; i < _items.Size; i++)
free(_items[i]);
_items.clear();
}
void ImGuiLogger::addLog(const char *fmt, ...) {
// FIXME-OPT
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
_items.push_back(scumm_strdup(buf));
// FIXME-OPT
char buf[1024];
va_list args;
va_start(args, fmt);
vsnprintf(buf, IM_ARRAYSIZE(buf), fmt, args);
buf[IM_ARRAYSIZE(buf) - 1] = 0;
va_end(args);
_items.push_back(scumm_strdup(buf));
}
void ImGuiLogger::draw(const char *title, bool *p_open) {
if (!*p_open)
return;
if (!*p_open)
return;
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open)) {
ImGui::End();
return;
}
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin(title, p_open)) {
ImGui::End();
return;
}
// As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
// Here we create a context menu only available from the title bar.
if (ImGui::BeginPopupContextItem()) {
if (ImGui::MenuItem("Close ImGuiLogger"))
*p_open = false;
ImGui::EndPopup();
}
// As a specific feature guaranteed by the library, after calling Begin() the last Item represent the title bar. So e.g. IsItemHovered() will return true when hovering the title bar.
// Here we create a context menu only available from the title bar.
if (ImGui::BeginPopupContextItem()) {
if (ImGui::MenuItem("Close ImGuiLogger"))
*p_open = false;
ImGui::EndPopup();
}
// Clear
if (ImGui::Button(ICON_MS_CLEAR_ALL)) {
clear();
}
ImGui::SetItemTooltip("Clear");
ImGui::SameLine();
// Clear
if (ImGui::Button(ICON_MS_CLEAR_ALL)) {
clear();
}
ImGui::SetItemTooltip("Clear");
ImGui::SameLine();
// Copy
bool copy_to_clipboard = ImGui::Button(ICON_MS_CONTENT_COPY);
ImGui::SetItemTooltip("Copy to clipboard");
ImGui::SameLine();
// Copy
bool copy_to_clipboard = ImGui::Button(ICON_MS_CONTENT_COPY);
ImGui::SetItemTooltip("Copy to clipboard");
ImGui::SameLine();
// debug channels
int numChannels = 0;
auto channels = DebugMan.getDebugChannels();
for (auto &channel : channels) {
if (channel.name == "imgui")
continue;
bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
if (enabled)
numChannels++;
}
// debug channels
int numChannels = 0;
auto channels = DebugMan.getDebugChannels();
for (auto &channel : channels) {
if (channel.name == "imgui")
continue;
bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
if (enabled)
numChannels++;
}
Common::String selChannels(Common::String::format("(%d channel%s)", numChannels, numChannels > 1 ? "s" : ""));
ImGui::PushItemWidth(120);
if (ImGui::BeginCombo("##Channels", selChannels.c_str())) {
for (auto &channel : channels) {
if (channel.name == "imgui")
continue;
bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
if (ImGui::Checkbox(channel.name.c_str(), &enabled)) {
if (enabled) {
DebugMan.enableDebugChannel(channel.channel);
} else {
DebugMan.disableDebugChannel(channel.channel);
}
}
ImGui::SetItemTooltip("%s", channel.description.c_str());
}
ImGui::EndCombo();
}
ImGui::SameLine();
Common::String selChannels(Common::String::format("(%d channel%s)", numChannels, numChannels > 1 ? "s" : ""));
ImGui::PushItemWidth(120);
if (ImGui::BeginCombo("##Channels", selChannels.c_str())) {
for (auto &channel : channels) {
if (channel.name == "imgui")
continue;
bool enabled = DebugMan.isDebugChannelEnabled(channel.channel);
if (ImGui::Checkbox(channel.name.c_str(), &enabled)) {
if (enabled) {
DebugMan.enableDebugChannel(channel.channel);
} else {
DebugMan.disableDebugChannel(channel.channel);
}
}
ImGui::SetItemTooltip("%s", channel.description.c_str());
}
ImGui::EndCombo();
}
ImGui::SameLine();
// Options menu
if (ImGui::BeginPopup("Options")) {
if (ImGui::InputInt("Debug Level", &gDebugLevel)) {
if (gDebugLevel < 0)
gDebugLevel = 0;
}
ImGui::Separator();
ImGui::Checkbox("Auto-scroll", &_autoScroll);
ImGui::EndPopup();
}
// Options menu
if (ImGui::BeginPopup("Options")) {
if (ImGui::InputInt("Debug Level", &gDebugLevel)) {
if (gDebugLevel < 0)
gDebugLevel = 0;
}
ImGui::Separator();
ImGui::Checkbox("Auto-scroll", &_autoScroll);
ImGui::EndPopup();
}
// Options, Filter
if (ImGui::Button(ICON_MS_SETTINGS))
ImGui::OpenPopup("Options");
ImGui::SetItemTooltip("Options");
ImGui::SameLine();
// Options, Filter
if (ImGui::Button(ICON_MS_SETTINGS))
ImGui::OpenPopup("Options");
ImGui::SetItemTooltip("Options");
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
ImGui::Spacing();
ImGui::SameLine();
// Error
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_error_b);
toggleButton("\ue160", &_showError);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Errors");
ImGui::SameLine();
// Error
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_error_b);
ImGuiEx::toggleButton("\ue160", &_showError);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Errors");
ImGui::SameLine();
// Warning
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_warning_b);
toggleButton("\ue002", &_showWarn);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Warnings");
ImGui::SameLine();
// Warning
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_warning_b);
ImGuiEx::toggleButton("\ue002", &_showWarn);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Warnings");
ImGui::SameLine();
// Info
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_info_b);
toggleButton(ICON_MS_INFO, &_showInfo);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Info");
ImGui::SameLine();
// Info
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_info_b);
ImGuiEx::toggleButton(ICON_MS_INFO, &_showInfo);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Info");
ImGui::SameLine();
// Debug
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_debug_b);
toggleButton(ICON_MS_BUG_REPORT, &_showdebug);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Debug");
ImGui::SameLine();
// Debug
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_debug_b);
ImGuiEx::toggleButton(ICON_MS_BUG_REPORT, &_showdebug);
ImGui::PopStyleColor();
ImGui::SetItemTooltip("Show Debug");
ImGui::SameLine();
_filter.Draw("Filter (\"incl,-excl\") (\"warn\")", 180);
ImGui::Separator();
_filter.Draw("Filter (\"incl,-excl\") (\"warn\")", 180);
ImGui::Separator();
ImGui::BeginChild("ScrollingRegion", ImVec2(), false, ImGuiWindowFlags_HorizontalScrollbar);
if (ImGui::BeginPopupContextWindow()) {
if (ImGui::Selectable(ICON_MS_CLEAR_ALL " Clear"))
clear();
if (ImGui::Selectable(ICON_MS_CONTENT_COPY " Copy"))
copy_to_clipboard = true;
ImGui::EndPopup();
}
ImGui::BeginChild("ScrollingRegion", ImVec2(), false, ImGuiWindowFlags_HorizontalScrollbar);
if (ImGui::BeginPopupContextWindow()) {
if (ImGui::Selectable(ICON_MS_CLEAR_ALL " Clear"))
clear();
if (ImGui::Selectable(ICON_MS_CONTENT_COPY " Copy"))
copy_to_clipboard = true;
ImGui::EndPopup();
}
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
if (copy_to_clipboard)
ImGui::LogToClipboard();
for (int i = 0; i < _items.Size; i++) {
const char *item = _items[i];
bool isError = strstr(item, "[error]");
if (!_showError && isError)
continue;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(4, 1)); // Tighten spacing
if (copy_to_clipboard)
ImGui::LogToClipboard();
for (int i = 0; i < _items.Size; i++) {
const char *item = _items[i];
bool isError = strstr(item, "[error]");
if (!_showError && isError)
continue;
bool isWarn = strstr(item, "[warn]");
if (!_showWarn && isWarn)
continue;
bool isWarn = strstr(item, "[warn]");
if (!_showWarn && isWarn)
continue;
bool isDebug = strstr(item, "[debug]");
if (!_showdebug && isDebug)
continue;
bool isDebug = strstr(item, "[debug]");
if (!_showdebug && isDebug)
continue;
if (!_showInfo && !isError && !isWarn && !isDebug)
continue;
if (!_showInfo && !isError && !isWarn && !isDebug)
continue;
if (!_filter.PassFilter(item))
continue;
if (!_filter.PassFilter(item))
continue;
// Normally you would store more information in your item (e.g. make _items[] an array of structure, store color/type etc.)
bool pop_color = false;
if (isError) {
item += 7;
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_error);
pop_color = true;
} else if (isWarn) {
item += 6;
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_warning);
pop_color = true;
} else if (isDebug) {
item += 7;
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_debug);
pop_color = true;
} else if (strncmp(item, "> ", 2) == 0) {
ImGui::PushStyleColor(ImGuiCol_Text, _state->_colors._logger_info);
pop_color = true;
}
ImGui::TextUnformatted(item);
if (pop_color)
ImGui::PopStyleColor();
}
if (copy_to_clipboard)
ImGui::LogFinish();
// Normally you would store more information in your item (e.g. make _items[] an array of structure, store color/type etc.)
bool pop_color = false;
if (isError) {
item += 7;
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_error);
pop_color = true;
} else if (isWarn) {
item += 6;
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_warning);
pop_color = true;
} else if (isDebug) {
item += 7;
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_debug);
pop_color = true;
} else if (strncmp(item, "> ", 2) == 0) {
ImGui::PushStyleColor(ImGuiCol_Text, _colors._logger_info);
pop_color = true;
}
ImGui::TextUnformatted(item);
if (pop_color)
ImGui::PopStyleColor();
}
if (copy_to_clipboard)
ImGui::LogFinish();
if (_scrollToBottom || (_autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
ImGui::SetScrollHereY(1.0f);
_scrollToBottom = false;
if (_scrollToBottom || (_autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
ImGui::SetScrollHereY(1.0f);
_scrollToBottom = false;
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::End();
ImGui::PopStyleVar();
ImGui::EndChild();
ImGui::End();
}
void ImGuiLogger::drawColorOptions() {
ImGui::SeparatorText("Logger");
ImGui::ColorEdit4("Error", &_colors._logger_error.x);
ImGui::ColorEdit4("Error Button", &_colors._logger_error_b.x);
ImGui::ColorEdit4("Warning", &_colors._logger_warning.x);
ImGui::ColorEdit4("Warning Button", &_colors._logger_warning_b.x);
ImGui::ColorEdit4("Info", &_colors._logger_info.x);
ImGui::ColorEdit4("Info Button", &_colors._logger_info_b.x);
ImGui::ColorEdit4("Debug", &_colors._logger_debug.x);
ImGui::ColorEdit4("Debug Button", &_colors._logger_debug_b.x);
}
} // namespace DT
+67
View File
@@ -0,0 +1,67 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef DIRECTOR_DEBUGER_DT_LOGGER_H
#define DIRECTOR_DEBUGER_DT_LOGGER_H
#include "backends/imgui/imgui.h"
namespace Director {
namespace DT {
class ImGuiLogger {
char _inputBuf[256];
ImVector<char *> _items;
ImVector<char *> _history;
int _historyPos; // -1: new line, 0.._history.Size-1 browsing history.
ImGuiTextFilter _filter;
bool _autoScroll;
bool _scrollToBottom;
bool _showError = true;
bool _showWarn = true;
bool _showInfo = true;
bool _showdebug = true;
struct {
ImVec4 _logger_error_b = ImVec4(1.f, 0.f, 0.f, 1.f);
ImVec4 _logger_warning_b = ImVec4(1.f, 1.f, 0.f, 1.f);
ImVec4 _logger_info_b = ImVec4(1.f, 1.f, 1.f, 1.f);
ImVec4 _logger_debug_b = ImVec4(0.8f, 0.8f, 0.8f, 1.f);
ImVec4 _logger_error = ImVec4(1.0f, 0.4f, 0.4f, 1.0f);
ImVec4 _logger_warning = ImVec4(1.0f, 1.0f, 0.4f, 1.0f);
ImVec4 _logger_info = ImVec4(1.0f, 0.8f, 0.6f, 1.0f);
ImVec4 _logger_debug = ImVec4(0.8f, 0.8f, 0.8f, 1.0f);
} _colors;
public:
ImGuiLogger();
~ImGuiLogger();
void clear();
void addLog(const char *fmt, ...) IM_FMTARGS(2);
void drawColorOptions();
void draw(const char *title, bool *p_open);
};
} // namespace DT
} // namespace Director
#endif
+3 -2
View File
@@ -20,6 +20,7 @@
*/
#include "backends/imgui/IconsMaterialSymbols.h"
#include "backends/imgui/imgui_utils.h"
#include "director/director.h"
#include "director/debugger/dt-internal.h"
@@ -221,11 +222,11 @@ void showScripts() {
if (!_state->_functions._scripts[_state->_functions._current].oldAst) {
ImGui::SameLine(0, 20);
toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
ImGuiEx::toggleButton(ICON_MS_PACKAGE_2, &_state->_functions._showByteCode, true); // Lingo
ImGui::SetItemTooltip("Lingo");
ImGui::SameLine();
toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
ImGuiEx::toggleButton(ICON_MS_STACKS, &_state->_functions._showByteCode); // Bytecode
ImGui::SetItemTooltip("Bytecode");
}