Add flags, file mgmt, widgets to zeml
This commit is contained in:
@@ -4,12 +4,16 @@
|
|||||||
#include <imgui/imgui.h>
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
#include <fstream>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "app/gui/canvas.h"
|
||||||
|
#include "app/gui/input.h"
|
||||||
|
|
||||||
namespace yaze {
|
namespace yaze {
|
||||||
namespace app {
|
namespace app {
|
||||||
namespace gui {
|
namespace gui {
|
||||||
@@ -58,6 +62,7 @@ WidgetType MapType(const std::string& type) {
|
|||||||
{"Text", WidgetType::Text},
|
{"Text", WidgetType::Text},
|
||||||
{"CollapsingHeader", WidgetType::CollapsingHeader},
|
{"CollapsingHeader", WidgetType::CollapsingHeader},
|
||||||
{"Columns", WidgetType::Columns},
|
{"Columns", WidgetType::Columns},
|
||||||
|
{"Checkbox", WidgetType::Checkbox},
|
||||||
{"HexInputByte", WidgetType::HexInputByte},
|
{"HexInputByte", WidgetType::HexInputByte},
|
||||||
{"HexInputWord", WidgetType::HexInputWord},
|
{"HexInputWord", WidgetType::HexInputWord},
|
||||||
{"Table", WidgetType::Table},
|
{"Table", WidgetType::Table},
|
||||||
@@ -71,12 +76,17 @@ WidgetType MapType(const std::string& type) {
|
|||||||
{"MenuItem", WidgetType::MenuItem},
|
{"MenuItem", WidgetType::MenuItem},
|
||||||
{"BeginMenuBar", WidgetType::BeginMenuBar},
|
{"BeginMenuBar", WidgetType::BeginMenuBar},
|
||||||
{"Separator", WidgetType::Separator},
|
{"Separator", WidgetType::Separator},
|
||||||
|
{"BeginTabBar", WidgetType::BeginTabBar},
|
||||||
|
{"BeginTabItem", WidgetType::BeginTabItem},
|
||||||
|
{"Canvas", WidgetType::Canvas},
|
||||||
|
{"ref", WidgetType::Definition},
|
||||||
};
|
};
|
||||||
return typeMap[type];
|
return typeMap[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
||||||
const std::map<std::string, void*>& data_bindings) {
|
const std::map<std::string, void*>& data_bindings,
|
||||||
|
const std::map<std::string, Node>& definitions) {
|
||||||
Node node;
|
Node node;
|
||||||
if (index >= tokens.size() || tokens[index].type == TokenType::EndOfStream) {
|
if (index >= tokens.size() || tokens[index].type == TokenType::EndOfStream) {
|
||||||
return node;
|
return node;
|
||||||
@@ -88,8 +98,14 @@ Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
|||||||
if (token.type == TokenType::Identifier) {
|
if (token.type == TokenType::Identifier) {
|
||||||
node.type = MapType(token.value);
|
node.type = MapType(token.value);
|
||||||
index++; // Move to the next token for attributes
|
index++; // Move to the next token for attributes
|
||||||
node.attributes =
|
if (node.type == WidgetType::Definition) {
|
||||||
ParseAttributes(tokens, index, node.type, data_bindings);
|
if (definitions.find(token.value) != definitions.end()) {
|
||||||
|
node = definitions.at(token.value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.attributes =
|
||||||
|
ParseAttributes(tokens, index, node.type, data_bindings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the opening brace indicating the start of child nodes
|
// Handle the opening brace indicating the start of child nodes
|
||||||
@@ -116,6 +132,150 @@ Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParseFlags(const WidgetType& type, const std::string& flags,
|
||||||
|
WidgetAttributes& attributes) {
|
||||||
|
// Parse the flags for the `|` character
|
||||||
|
std::vector<std::string> flag_tokens;
|
||||||
|
std::string token;
|
||||||
|
std::istringstream tokenStream(flags);
|
||||||
|
while (std::getline(tokenStream, token, '|')) {
|
||||||
|
flag_tokens.push_back(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case WidgetType::BeginChild: {
|
||||||
|
static std::map<std::string, ImGuiWindowFlags> flagMap = {
|
||||||
|
{"None", ImGuiWindowFlags_None},
|
||||||
|
{"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
|
||||||
|
{"NoResize", ImGuiWindowFlags_NoResize},
|
||||||
|
{"NoMove", ImGuiWindowFlags_NoMove},
|
||||||
|
{"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
|
||||||
|
{"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
|
||||||
|
{"NoCollapse", ImGuiWindowFlags_NoCollapse},
|
||||||
|
{"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
|
||||||
|
{"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
|
||||||
|
{"NoInputs", ImGuiWindowFlags_NoInputs},
|
||||||
|
{"MenuBar", ImGuiWindowFlags_MenuBar},
|
||||||
|
{"HorizontalScrollbar", ImGuiWindowFlags_HorizontalScrollbar},
|
||||||
|
{"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
|
||||||
|
{"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
|
||||||
|
{"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
|
||||||
|
{"AlwaysHorizontalScrollbar",
|
||||||
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar},
|
||||||
|
{"AlwaysUseWindowPadding", ImGuiWindowFlags_AlwaysUseWindowPadding},
|
||||||
|
{"NoNavInputs", ImGuiWindowFlags_NoNavInputs},
|
||||||
|
{"NoNavFocus", ImGuiWindowFlags_NoNavFocus},
|
||||||
|
{"UnsavedDocument", ImGuiWindowFlags_UnsavedDocument},
|
||||||
|
{"NoNav", ImGuiWindowFlags_NoNav},
|
||||||
|
{"NoDecoration", ImGuiWindowFlags_NoDecoration},
|
||||||
|
{"NoInputs", ImGuiWindowFlags_NoInputs},
|
||||||
|
{"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
|
||||||
|
{"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
|
||||||
|
{"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
|
||||||
|
{"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
|
||||||
|
{"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
|
||||||
|
{"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
|
||||||
|
{"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
|
||||||
|
{"NoResize", ImGuiWindowFlags_NoResize},
|
||||||
|
{"NoMove", ImGuiWindowFlags_NoMove},
|
||||||
|
{"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
|
||||||
|
{"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
|
||||||
|
{"NoCollapse", ImGuiWindowFlags_NoCollapse},
|
||||||
|
{"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
|
||||||
|
{"AlwaysHorizontalScrollbar",
|
||||||
|
ImGuiWindowFlags_AlwaysHorizontalScrollbar}};
|
||||||
|
ImGuiWindowFlags windowFlags = ImGuiWindowFlags_None;
|
||||||
|
for (const auto& flag : flag_tokens) {
|
||||||
|
if (flagMap.find(flag) != flagMap.end()) {
|
||||||
|
windowFlags |= flagMap[flag];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attributes.flags = new ImGuiWindowFlags(windowFlags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WidgetType::Table: {
|
||||||
|
// Create a flag map
|
||||||
|
static std::map<std::string, ImGuiTableFlags> flagMap = {
|
||||||
|
{"None", ImGuiTableFlags_None},
|
||||||
|
{"Resizable", ImGuiTableFlags_Resizable},
|
||||||
|
{"Reorderable", ImGuiTableFlags_Reorderable},
|
||||||
|
{"Hideable", ImGuiTableFlags_Hideable},
|
||||||
|
{"Sortable", ImGuiTableFlags_Sortable},
|
||||||
|
{"NoSavedSettings", ImGuiTableFlags_NoSavedSettings},
|
||||||
|
{"ContextMenuInBody", ImGuiTableFlags_ContextMenuInBody},
|
||||||
|
{"RowBg", ImGuiTableFlags_RowBg},
|
||||||
|
{"BordersInnerH", ImGuiTableFlags_BordersInnerH},
|
||||||
|
{"BordersOuterH", ImGuiTableFlags_BordersOuterH},
|
||||||
|
{"BordersInnerV", ImGuiTableFlags_BordersInnerV},
|
||||||
|
{"BordersOuterV", ImGuiTableFlags_BordersOuterV},
|
||||||
|
{"BordersH", ImGuiTableFlags_BordersH},
|
||||||
|
{"BordersV", ImGuiTableFlags_BordersV},
|
||||||
|
{"Borders", ImGuiTableFlags_Borders},
|
||||||
|
{"NoBordersInBody", ImGuiTableFlags_NoBordersInBody},
|
||||||
|
{"NoBordersInBodyUntilResize",
|
||||||
|
ImGuiTableFlags_NoBordersInBodyUntilResize},
|
||||||
|
{"SizingFixedFit", ImGuiTableFlags_SizingFixedFit},
|
||||||
|
{"SizingFixedSame", ImGuiTableFlags_SizingFixedSame},
|
||||||
|
{"SizingStretchProp", ImGuiTableFlags_SizingStretchProp},
|
||||||
|
{"SizingStretchSame", ImGuiTableFlags_SizingStretchSame},
|
||||||
|
{"NoHostExtendX", ImGuiTableFlags_NoHostExtendX},
|
||||||
|
{"NoHostExtendY", ImGuiTableFlags_NoHostExtendY},
|
||||||
|
{"NoKeepColumnsVisible", ImGuiTableFlags_NoKeepColumnsVisible},
|
||||||
|
{"PreciseWidths", ImGuiTableFlags_PreciseWidths},
|
||||||
|
{"NoClip", ImGuiTableFlags_NoClip},
|
||||||
|
{"PadOuterX", ImGuiTableFlags_PadOuterX},
|
||||||
|
{"NoPadOuterX", ImGuiTableFlags_NoPadOuterX},
|
||||||
|
{"NoPadInnerX", ImGuiTableFlags_NoPadInnerX},
|
||||||
|
{"ScrollX", ImGuiTableFlags_ScrollX},
|
||||||
|
{"ScrollY", ImGuiTableFlags_ScrollY},
|
||||||
|
{"SortMulti", ImGuiTableFlags_SortMulti},
|
||||||
|
{"SortTristate", ImGuiTableFlags_SortTristate}};
|
||||||
|
ImGuiTableFlags tableFlags = ImGuiTableFlags_None;
|
||||||
|
for (const auto& flag : flag_tokens) {
|
||||||
|
if (flagMap.find(flag) != flagMap.end()) {
|
||||||
|
tableFlags |= flagMap[flag];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reserve data to the void* pointer and assign flags
|
||||||
|
attributes.flags = new ImGuiTableFlags(tableFlags);
|
||||||
|
} break;
|
||||||
|
case WidgetType::TableSetupColumn: {
|
||||||
|
static std::map<std::string, ImGuiTableColumnFlags> flagMap = {
|
||||||
|
{"None", ImGuiTableColumnFlags_None},
|
||||||
|
{"DefaultHide", ImGuiTableColumnFlags_DefaultHide},
|
||||||
|
{"DefaultSort", ImGuiTableColumnFlags_DefaultSort},
|
||||||
|
{"WidthStretch", ImGuiTableColumnFlags_WidthStretch},
|
||||||
|
{"WidthFixed", ImGuiTableColumnFlags_WidthFixed},
|
||||||
|
{"NoResize", ImGuiTableColumnFlags_NoResize},
|
||||||
|
{"NoReorder", ImGuiTableColumnFlags_NoReorder},
|
||||||
|
{"NoHide", ImGuiTableColumnFlags_NoHide},
|
||||||
|
{"NoClip", ImGuiTableColumnFlags_NoClip},
|
||||||
|
{"NoSort", ImGuiTableColumnFlags_NoSort},
|
||||||
|
{"NoSortAscending", ImGuiTableColumnFlags_NoSortAscending},
|
||||||
|
{"NoSortDescending", ImGuiTableColumnFlags_NoSortDescending},
|
||||||
|
{"NoHeaderWidth", ImGuiTableColumnFlags_NoHeaderWidth},
|
||||||
|
{"PreferSortAscending", ImGuiTableColumnFlags_PreferSortAscending},
|
||||||
|
{"PreferSortDescending", ImGuiTableColumnFlags_PreferSortDescending},
|
||||||
|
{"IndentEnable", ImGuiTableColumnFlags_IndentEnable},
|
||||||
|
{"IndentDisable", ImGuiTableColumnFlags_IndentDisable},
|
||||||
|
{"IsEnabled", ImGuiTableColumnFlags_IsEnabled},
|
||||||
|
{"IsVisible", ImGuiTableColumnFlags_IsVisible},
|
||||||
|
{"IsSorted", ImGuiTableColumnFlags_IsSorted},
|
||||||
|
{"IsHovered", ImGuiTableColumnFlags_IsHovered}};
|
||||||
|
ImGuiTableColumnFlags columnFlags = ImGuiTableColumnFlags_None;
|
||||||
|
for (const auto& flag : flag_tokens) {
|
||||||
|
if (flagMap.find(flag) != flagMap.end()) {
|
||||||
|
columnFlags |= flagMap[flag];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reserve data to the void* pointer and assign flags
|
||||||
|
attributes.flags = new ImGuiTableColumnFlags(columnFlags);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WidgetAttributes ParseAttributes(
|
WidgetAttributes ParseAttributes(
|
||||||
const std::vector<Token>& tokens, size_t& index, const WidgetType& type,
|
const std::vector<Token>& tokens, size_t& index, const WidgetType& type,
|
||||||
const std::map<std::string, void*>& data_bindings) {
|
const std::map<std::string, void*>& data_bindings) {
|
||||||
@@ -139,6 +299,13 @@ WidgetAttributes ParseAttributes(
|
|||||||
attributes.max = std::stod(value);
|
attributes.max = std::stod(value);
|
||||||
else if (keyToken.value == "value")
|
else if (keyToken.value == "value")
|
||||||
attributes.value = std::stod(value);
|
attributes.value = std::stod(value);
|
||||||
|
else if (keyToken.value == "width")
|
||||||
|
if (value == "autox")
|
||||||
|
attributes.width = ImGui::GetContentRegionAvail().x;
|
||||||
|
else if (value == "autoy")
|
||||||
|
attributes.width = ImGui::GetContentRegionAvail().y;
|
||||||
|
else
|
||||||
|
attributes.width = std::stod(value);
|
||||||
else if (keyToken.value == "text")
|
else if (keyToken.value == "text")
|
||||||
attributes.text = value;
|
attributes.text = value;
|
||||||
else if (keyToken.value == "data" &&
|
else if (keyToken.value == "data" &&
|
||||||
@@ -147,7 +314,7 @@ WidgetAttributes ParseAttributes(
|
|||||||
} else if (keyToken.value == "count") {
|
} else if (keyToken.value == "count") {
|
||||||
attributes.count = std::stoi(value);
|
attributes.count = std::stoi(value);
|
||||||
} else if (keyToken.value == "flags") {
|
} else if (keyToken.value == "flags") {
|
||||||
attributes.flags = nullptr; // Placeholder for future use
|
ParseFlags(type, value, attributes);
|
||||||
} else if (keyToken.value == "size") {
|
} else if (keyToken.value == "size") {
|
||||||
attributes.size = ImVec2(0, 0); // Placeholder for future use
|
attributes.size = ImVec2(0, 0); // Placeholder for future use
|
||||||
}
|
}
|
||||||
@@ -160,19 +327,54 @@ WidgetAttributes ParseAttributes(
|
|||||||
return attributes;
|
return attributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node Parse(const std::string& yazon_input,
|
||||||
|
const std::map<std::string, void*>& data_bindings) {
|
||||||
|
size_t index = 0;
|
||||||
|
auto tokens = Tokenize(yazon_input);
|
||||||
|
|
||||||
|
std::map<std::string, Node> definitions;
|
||||||
|
if (tokens[index].value == "Definitions") {
|
||||||
|
index++; // Skip the "Definitions" token
|
||||||
|
while (index < tokens.size() &&
|
||||||
|
tokens[index].value != "Layout") { // Skip the definitions
|
||||||
|
// Get the definition name and parse the node
|
||||||
|
std::string definition_name = tokens[index].value;
|
||||||
|
index++; // Move to the definition node
|
||||||
|
definitions[definition_name] = ParseNode(tokens, index, data_bindings);
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParseNode(tokens, index, data_bindings);
|
||||||
|
}
|
||||||
|
|
||||||
void Render(Node& node) {
|
void Render(Node& node) {
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
case WidgetType::Window:
|
case WidgetType::Window: {
|
||||||
if (ImGui::Begin(node.attributes.title.c_str())) {
|
ImGuiWindowFlags flags = ImGuiWindowFlags_None;
|
||||||
|
if (node.attributes.flags) {
|
||||||
|
flags = *(ImGuiWindowFlags*)node.attributes.flags;
|
||||||
|
}
|
||||||
|
if (ImGui::Begin(node.attributes.title.c_str(), nullptr, flags)) {
|
||||||
for (auto& child : node.children) {
|
for (auto& child : node.children) {
|
||||||
Render(child);
|
Render(child);
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
case WidgetType::Button:
|
case WidgetType::Button:
|
||||||
if (ImGui::Button(node.attributes.text.c_str())) {
|
if (node.attributes.data) {
|
||||||
ExecuteActions(node.actions, ActionType::Click);
|
// Format the text with the data value
|
||||||
|
char formattedText[256];
|
||||||
|
snprintf(formattedText, sizeof(formattedText),
|
||||||
|
node.attributes.text.c_str(), *(int*)node.attributes.data);
|
||||||
|
if (ImGui::Button(formattedText)) {
|
||||||
|
ExecuteActions(node.actions, ActionType::Click);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ImGui::Button(node.attributes.text.c_str())) {
|
||||||
|
ExecuteActions(node.actions, ActionType::Click);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WidgetType::CollapsingHeader:
|
case WidgetType::CollapsingHeader:
|
||||||
@@ -192,24 +394,37 @@ void Render(Node& node) {
|
|||||||
ImGui::Columns(1);
|
ImGui::Columns(1);
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
break;
|
break;
|
||||||
case WidgetType::Table:
|
case WidgetType::Checkbox:
|
||||||
ImGui::BeginTable(node.attributes.id.c_str(), node.attributes.count);
|
if (ImGui::Checkbox(node.attributes.title.c_str(),
|
||||||
for (auto& child : node.children) {
|
(bool*)node.attributes.data)) {
|
||||||
Render(child);
|
ExecuteActions(node.actions, ActionType::Change);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WidgetType::Table: {
|
||||||
|
ImGuiTableFlags flags = ImGuiTableFlags_None;
|
||||||
|
if (node.attributes.flags) {
|
||||||
|
flags = *(ImGuiTableFlags*)node.attributes.flags;
|
||||||
|
}
|
||||||
|
if (ImGui::BeginTable(node.attributes.id.c_str(), node.attributes.count,
|
||||||
|
flags)) {
|
||||||
|
for (auto& child : node.children) {
|
||||||
|
Render(child);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndTable();
|
ImGui::EndTable();
|
||||||
break;
|
} break;
|
||||||
case WidgetType::TableSetupColumn:
|
case WidgetType::TableSetupColumn: {
|
||||||
ImGui::TableSetupColumn(node.attributes.title.c_str());
|
ImGuiTableColumnFlags flags = ImGuiTableColumnFlags_None;
|
||||||
break;
|
if (node.attributes.flags) {
|
||||||
|
flags = *(ImGuiTableColumnFlags*)node.attributes.flags;
|
||||||
|
}
|
||||||
|
ImGui::TableSetupColumn(node.attributes.title.c_str(), flags);
|
||||||
|
} break;
|
||||||
case WidgetType::TableHeadersRow:
|
case WidgetType::TableHeadersRow:
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
break;
|
break;
|
||||||
case WidgetType::TableNextColumn:
|
case WidgetType::TableNextColumn:
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
for (auto& child : node.children) {
|
|
||||||
Render(child);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case WidgetType::Text:
|
case WidgetType::Text:
|
||||||
if (node.attributes.data) {
|
if (node.attributes.data) {
|
||||||
@@ -260,18 +475,52 @@ void Render(Node& node) {
|
|||||||
case WidgetType::Separator:
|
case WidgetType::Separator:
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
break;
|
break;
|
||||||
|
case WidgetType::Selectable:
|
||||||
|
if (ImGui::Selectable(node.attributes.title.c_str(),
|
||||||
|
(bool*)node.attributes.selected)) {
|
||||||
|
ExecuteActions(node.actions, ActionType::Click);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WidgetType::BeginTabBar:
|
||||||
|
if (ImGui::BeginTabBar(node.attributes.title.c_str())) {
|
||||||
|
for (auto& child : node.children) {
|
||||||
|
Render(child);
|
||||||
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WidgetType::BeginTabItem:
|
||||||
|
if (ImGui::BeginTabItem(node.attributes.title.c_str())) {
|
||||||
|
for (auto& child : node.children) {
|
||||||
|
Render(child);
|
||||||
|
}
|
||||||
|
ImGui::EndTabItem();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case WidgetType::HexInputByte:
|
||||||
|
gui::InputHexByte(node.attributes.id.c_str(),
|
||||||
|
(uint8_t*)node.attributes.data);
|
||||||
|
break;
|
||||||
|
case WidgetType::HexInputWord:
|
||||||
|
gui::InputHexWord(node.attributes.id.c_str(),
|
||||||
|
(uint16_t*)node.attributes.data);
|
||||||
|
break;
|
||||||
|
case WidgetType::Canvas: {
|
||||||
|
gui::Canvas* canvas = (gui::Canvas*)node.attributes.data;
|
||||||
|
if (canvas) {
|
||||||
|
canvas->DrawBackground();
|
||||||
|
canvas->DrawContextMenu();
|
||||||
|
|
||||||
|
canvas->DrawGrid();
|
||||||
|
canvas->DrawOverlay();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Node Parse(const std::string& yazon_input,
|
|
||||||
const std::map<std::string, void*>& data_bindings) {
|
|
||||||
size_t index = 0;
|
|
||||||
auto tokens = Tokenize(yazon_input);
|
|
||||||
return ParseNode(tokens, index, data_bindings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExecuteActions(const std::vector<Action>& actions, ActionType type) {
|
void ExecuteActions(const std::vector<Action>& actions, ActionType type) {
|
||||||
for (const auto& action : actions) {
|
for (const auto& action : actions) {
|
||||||
if (action.type == type) {
|
if (action.type == type) {
|
||||||
@@ -294,6 +543,33 @@ void BindAction(Node* node, ActionType type, std::function<void()> callback) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BindSelectable(Node* node, bool* selected,
|
||||||
|
std::function<void()> callback) {
|
||||||
|
if (node) {
|
||||||
|
Action action = {ActionType::Click, callback};
|
||||||
|
node->actions.push_back(action);
|
||||||
|
node->attributes.selected = selected;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string LoadFile(const std::string& filename) {
|
||||||
|
std::string fileContents;
|
||||||
|
const std::string kPath = "assets/layouts/";
|
||||||
|
std::ifstream file(kPath + filename);
|
||||||
|
|
||||||
|
if (file.is_open()) {
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(file, line)) {
|
||||||
|
fileContents += line;
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
} else {
|
||||||
|
fileContents = "File not found: " + filename;
|
||||||
|
std::cout << fileContents << std::endl;
|
||||||
|
}
|
||||||
|
return fileContents;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace zeml
|
} // namespace zeml
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|||||||
@@ -54,15 +54,20 @@ enum class WidgetType {
|
|||||||
TableNextColumn,
|
TableNextColumn,
|
||||||
CollapsingHeader,
|
CollapsingHeader,
|
||||||
Columns,
|
Columns,
|
||||||
|
Checkbox,
|
||||||
Selectable,
|
Selectable,
|
||||||
Function,
|
Function,
|
||||||
BeginChild,
|
BeginChild,
|
||||||
BeginMenuBar,
|
BeginMenuBar,
|
||||||
BeginMenu,
|
BeginMenu,
|
||||||
|
BeginTabBar,
|
||||||
|
BeginTabItem,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
Separator,
|
Separator,
|
||||||
HexInputByte,
|
HexInputByte,
|
||||||
HexInputWord,
|
HexInputWord,
|
||||||
|
Canvas,
|
||||||
|
Definition,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -82,16 +87,17 @@ enum class WidgetType {
|
|||||||
*/
|
*/
|
||||||
struct WidgetAttributes {
|
struct WidgetAttributes {
|
||||||
std::string id;
|
std::string id;
|
||||||
std::string title; // For Window, Button
|
std::string title; // For Window, Button
|
||||||
double min; // For Slider
|
std::string text; // For Text, Button
|
||||||
double max; // For Slider
|
double min; // For Slider
|
||||||
double value; // For Slidecar
|
double max; // For Slider
|
||||||
std::string text; // For Text, Button
|
double value; // For Slidecar
|
||||||
int count = 0; // For Columns
|
float width; // For Columns
|
||||||
ImVec2 size = ImVec2(0, 0);
|
int count = 0; // For Columns
|
||||||
void* flags = nullptr;
|
ImVec2 size = ImVec2(0, 0); // For BeginChild
|
||||||
|
bool* selected = nullptr; // For Selectable
|
||||||
void* data = nullptr;
|
void* flags = nullptr; // For Various
|
||||||
|
void* data = nullptr; // For Various
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,8 +110,7 @@ enum class ActionType { Click, Change, Run };
|
|||||||
*/
|
*/
|
||||||
struct Action {
|
struct Action {
|
||||||
ActionType type;
|
ActionType type;
|
||||||
std::function<void()> callback; // Using std::function to hold lambda
|
std::function<void()> callback;
|
||||||
// expressions or function pointers
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -149,11 +154,25 @@ void Bind(Node* node, std::function<void()> callback);
|
|||||||
*/
|
*/
|
||||||
void BindAction(Node* node, ActionType type, std::function<void()> callback);
|
void BindAction(Node* node, ActionType type, std::function<void()> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bind a selectable node
|
||||||
|
*/
|
||||||
|
void BindSelectable(Node* node, bool* selected, std::function<void()> callback);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Map a string to a widget type
|
* @brief Map a string to a widget type
|
||||||
*/
|
*/
|
||||||
WidgetType MapType(const std::string& type);
|
WidgetType MapType(const std::string& type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parse a zeml definition
|
||||||
|
*/
|
||||||
|
void ParseDefinitions(const std::vector<Token>& tokens, size_t& index,
|
||||||
|
std::map<std::string, Node>& definitions);
|
||||||
|
|
||||||
|
void ParseFlags(const WidgetType& type, const std::string& flags,
|
||||||
|
WidgetAttributes& flags_ptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ParseNode attributes for a widget
|
* @brief ParseNode attributes for a widget
|
||||||
*/
|
*/
|
||||||
@@ -162,13 +181,14 @@ WidgetAttributes ParseAttributes(
|
|||||||
const std::map<std::string, void*>& data_bindings = {});
|
const std::map<std::string, void*>& data_bindings = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ParseNode a zeml node
|
* @brief Parse a zeml node
|
||||||
*/
|
*/
|
||||||
Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
Node ParseNode(const std::vector<Token>& tokens, size_t& index,
|
||||||
const std::map<std::string, void*>& data_bindings = {});
|
const std::map<std::string, void*>& data_bindings = {},
|
||||||
|
const std::map<std::string, Node>& definitions = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ParseNode a zeml string
|
* @brief Parse a zeml string
|
||||||
*/
|
*/
|
||||||
Node Parse(const std::string& yazon_input,
|
Node Parse(const std::string& yazon_input,
|
||||||
const std::map<std::string, void*>& data_bindings = {});
|
const std::map<std::string, void*>& data_bindings = {});
|
||||||
@@ -183,6 +203,8 @@ void Render(Node& node);
|
|||||||
*/
|
*/
|
||||||
void ExecuteActions(const std::vector<Action>& actions, ActionType type);
|
void ExecuteActions(const std::vector<Action>& actions, ActionType type);
|
||||||
|
|
||||||
|
std::string LoadFile(const std::string& filename);
|
||||||
|
|
||||||
} // namespace zeml
|
} // namespace zeml
|
||||||
} // namespace gui
|
} // namespace gui
|
||||||
} // namespace app
|
} // namespace app
|
||||||
|
|||||||
Reference in New Issue
Block a user