yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
zeml.cc
Go to the documentation of this file.
1
2#include "app/gui/zeml.h"
3
4#include <cctype>
5#include <fstream>
6#include <functional>
7#include <map>
8#include <sstream>
9#include <string>
10#include <vector>
11
13#include "app/gui/canvas.h"
14#include "app/gui/input.h"
15#include "imgui/imgui.h"
16
17namespace yaze {
18namespace app {
19namespace gui {
20namespace zeml {
21
22std::vector<Token> Tokenize(const std::string& input) {
23 std::vector<Token> tokens;
24 std::istringstream stream(input);
25 char ch;
26
27 while (stream.get(ch)) {
28 if (isspace(ch)) continue;
29
30 if (ch == '{') {
31 tokens.push_back({TokenType::OpenBrace, "{"});
32 } else if (ch == '}') {
33 tokens.push_back({TokenType::CloseBrace, "}"});
34 } else if (ch == ',') {
35 tokens.push_back({TokenType::Comma, ","});
36 } else if (std::isalnum(ch) || ch == '_') {
37 std::string ident(1, ch);
38 while (stream.get(ch) && (std::isalnum(ch) || ch == '_')) {
39 ident += ch;
40 }
41 stream.unget();
42 tokens.push_back({TokenType::Identifier, ident});
43 } else if (ch == '"' || ch == '\'') {
44 std::string str;
45 char quoteType = ch;
46 while (stream.get(ch) && ch != quoteType) {
47 str += ch;
48 }
49 tokens.push_back({TokenType::String, str});
50 }
51 }
52
53 tokens.push_back({TokenType::EndOfStream, ""});
54 return tokens;
55}
56
57WidgetType MapType(const std::string& type) {
58 static std::map<std::string, WidgetType> typeMap = {
59 {"Window", WidgetType::Window},
60 {"Button", WidgetType::Button},
61 {"Slider", WidgetType::Slider},
62 {"Text", WidgetType::Text},
63 {"CollapsingHeader", WidgetType::CollapsingHeader},
64 {"Columns", WidgetType::Columns},
65 {"Checkbox", WidgetType::Checkbox},
66 {"HexInputByte", WidgetType::HexInputByte},
67 {"HexInputWord", WidgetType::HexInputWord},
68 {"Table", WidgetType::Table},
69 {"Selectable", WidgetType::Selectable},
70 {"TableSetupColumn", WidgetType::TableSetupColumn},
71 {"TableHeadersRow", WidgetType::TableHeadersRow},
72 {"TableNextColumn", WidgetType::TableNextColumn},
73 {"Function", WidgetType::Function},
74 {"BeginChild", WidgetType::BeginChild},
75 {"BeginMenu", WidgetType::BeginMenu},
76 {"MenuItem", WidgetType::MenuItem},
77 {"BeginMenuBar", WidgetType::BeginMenuBar},
78 {"Separator", WidgetType::Separator},
79 {"BeginTabBar", WidgetType::BeginTabBar},
80 {"BeginTabItem", WidgetType::BeginTabItem},
81 {"Canvas", WidgetType::Canvas},
83 };
84 return typeMap[type];
85}
86
87Node ParseNode(const std::vector<Token>& tokens, size_t& index,
88 const std::map<std::string, void*>& data_bindings,
89 const std::map<std::string, Node>& definitions) {
90 Node node;
91 if (index >= tokens.size() || tokens[index].type == TokenType::EndOfStream) {
92 return node;
93 }
94
95 while (index < tokens.size() &&
96 tokens[index].type != TokenType::EndOfStream) {
97 Token token = tokens[index];
98 if (token.type == TokenType::Identifier) {
99 node.type = MapType(token.value);
100 index++; // Move to the next token for attributes
101 if (node.type == WidgetType::Definition) {
102 if (definitions.find(token.value) != definitions.end()) {
103 node = definitions.at(token.value);
104 }
105 } else {
106 node.attributes =
107 ParseAttributes(tokens, index, node.type, data_bindings);
108 }
109 }
110
111 // Handle the opening brace indicating the start of child nodes
112 if (index < tokens.size() && tokens[index].type == TokenType::OpenBrace) {
113 index++; // Skip the opening brace
114
115 while (index < tokens.size() &&
116 tokens[index].type != TokenType::CloseBrace) {
117 if (tokens[index].type == TokenType::Comma) {
118 index++; // Skip commas
119 } else {
120 node.children.push_back(ParseNode(tokens, index, data_bindings));
121 }
122 }
123
124 if (index < tokens.size() &&
125 tokens[index].type == TokenType::CloseBrace) {
126 index++; // Ensure closing brace is skipped before returning
127 }
128 }
129
130 break; // Exit after processing one complete node
131 }
132 return node;
133}
134
135void ParseFlags(const WidgetType& type, const std::string& flags,
136 WidgetAttributes& attributes) {
137 // Parse the flags for the `|` character
138 std::vector<std::string> flag_tokens;
139 std::string token;
140 std::istringstream tokenStream(flags);
141 while (std::getline(tokenStream, token, '|')) {
142 flag_tokens.push_back(token);
143 }
144
145 switch (type) {
147 static std::map<std::string, ImGuiWindowFlags> flagMap = {
148 {"None", ImGuiWindowFlags_None},
149 {"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
150 {"NoResize", ImGuiWindowFlags_NoResize},
151 {"NoMove", ImGuiWindowFlags_NoMove},
152 {"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
153 {"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
154 {"NoCollapse", ImGuiWindowFlags_NoCollapse},
155 {"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
156 {"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
157 {"NoInputs", ImGuiWindowFlags_NoInputs},
158 {"MenuBar", ImGuiWindowFlags_MenuBar},
159 {"HorizontalScrollbar", ImGuiWindowFlags_HorizontalScrollbar},
160 {"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
161 {"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
162 {"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
163 {"AlwaysHorizontalScrollbar",
164 ImGuiWindowFlags_AlwaysHorizontalScrollbar},
165 {"AlwaysUseWindowPadding", ImGuiWindowFlags_AlwaysUseWindowPadding},
166 {"NoNavInputs", ImGuiWindowFlags_NoNavInputs},
167 {"NoNavFocus", ImGuiWindowFlags_NoNavFocus},
168 {"UnsavedDocument", ImGuiWindowFlags_UnsavedDocument},
169 {"NoNav", ImGuiWindowFlags_NoNav},
170 {"NoDecoration", ImGuiWindowFlags_NoDecoration},
171 {"NoInputs", ImGuiWindowFlags_NoInputs},
172 {"NoFocusOnAppearing", ImGuiWindowFlags_NoFocusOnAppearing},
173 {"NoBringToFrontOnFocus", ImGuiWindowFlags_NoBringToFrontOnFocus},
174 {"AlwaysAutoResize", ImGuiWindowFlags_AlwaysAutoResize},
175 {"NoSavedSettings", ImGuiWindowFlags_NoSavedSettings},
176 {"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
177 {"NoMouseInputs", ImGuiWindowFlags_NoMouseInputs},
178 {"NoTitleBar", ImGuiWindowFlags_NoTitleBar},
179 {"NoResize", ImGuiWindowFlags_NoResize},
180 {"NoMove", ImGuiWindowFlags_NoMove},
181 {"NoScrollbar", ImGuiWindowFlags_NoScrollbar},
182 {"NoScrollWithMouse", ImGuiWindowFlags_NoScrollWithMouse},
183 {"NoCollapse", ImGuiWindowFlags_NoCollapse},
184 {"AlwaysVerticalScrollbar", ImGuiWindowFlags_AlwaysVerticalScrollbar},
185 {"AlwaysHorizontalScrollbar",
186 ImGuiWindowFlags_AlwaysHorizontalScrollbar}};
187 ImGuiWindowFlags windowFlags = ImGuiWindowFlags_None;
188 for (const auto& flag : flag_tokens) {
189 if (flagMap.find(flag) != flagMap.end()) {
190 windowFlags |= flagMap[flag];
191 }
192 }
193 attributes.flags = std::make_unique<ImGuiWindowFlags>(windowFlags);
194 break;
195 }
197 // Create a flag map using the tree node flags
198 static std::map<std::string, ImGuiTreeNodeFlags> flagMap = {
199 {"None", ImGuiTreeNodeFlags_None},
200 {"Selected", ImGuiTreeNodeFlags_Selected},
201 {"Framed", ImGuiTreeNodeFlags_Framed},
202 {"AllowItemOverlap", ImGuiTreeNodeFlags_AllowItemOverlap},
203 {"NoTreePushOnOpen", ImGuiTreeNodeFlags_NoTreePushOnOpen},
204 {"NoAutoOpenOnLog", ImGuiTreeNodeFlags_NoAutoOpenOnLog},
205 {"DefaultOpen", ImGuiTreeNodeFlags_DefaultOpen},
206 {"OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick},
207 {"OpenOnArrow", ImGuiTreeNodeFlags_OpenOnArrow},
208 {"Leaf", ImGuiTreeNodeFlags_Leaf},
209 {"Bullet", ImGuiTreeNodeFlags_Bullet},
210 {"FramePadding", ImGuiTreeNodeFlags_FramePadding},
211 {"NavLeftJumpsBackHere", ImGuiTreeNodeFlags_NavLeftJumpsBackHere},
212 {"CollapsingHeader", ImGuiTreeNodeFlags_CollapsingHeader}};
213 ImGuiTreeNodeFlags treeFlags = ImGuiTreeNodeFlags_None;
214 for (const auto& flag : flag_tokens) {
215 if (flagMap.find(flag) != flagMap.end()) {
216 treeFlags |= flagMap[flag];
217 }
218 }
219 attributes.flags = std::make_unique<ImGuiTreeNodeFlags>(treeFlags);
220 break;
221 }
222 case WidgetType::Table: {
223 // Create a flag map
224 static std::map<std::string, ImGuiTableFlags> flagMap = {
225 {"None", ImGuiTableFlags_None},
226 {"Resizable", ImGuiTableFlags_Resizable},
227 {"Reorderable", ImGuiTableFlags_Reorderable},
228 {"Hideable", ImGuiTableFlags_Hideable},
229 {"Sortable", ImGuiTableFlags_Sortable},
230 {"NoSavedSettings", ImGuiTableFlags_NoSavedSettings},
231 {"ContextMenuInBody", ImGuiTableFlags_ContextMenuInBody},
232 {"RowBg", ImGuiTableFlags_RowBg},
233 {"BordersInnerH", ImGuiTableFlags_BordersInnerH},
234 {"BordersOuterH", ImGuiTableFlags_BordersOuterH},
235 {"BordersInnerV", ImGuiTableFlags_BordersInnerV},
236 {"BordersOuterV", ImGuiTableFlags_BordersOuterV},
237 {"BordersH", ImGuiTableFlags_BordersH},
238 {"BordersV", ImGuiTableFlags_BordersV},
239 {"Borders", ImGuiTableFlags_Borders},
240 {"NoBordersInBody", ImGuiTableFlags_NoBordersInBody},
241 {"NoBordersInBodyUntilResize",
242 ImGuiTableFlags_NoBordersInBodyUntilResize},
243 {"SizingFixedFit", ImGuiTableFlags_SizingFixedFit},
244 {"SizingFixedSame", ImGuiTableFlags_SizingFixedSame},
245 {"SizingStretchProp", ImGuiTableFlags_SizingStretchProp},
246 {"SizingStretchSame", ImGuiTableFlags_SizingStretchSame},
247 {"NoHostExtendX", ImGuiTableFlags_NoHostExtendX},
248 {"NoHostExtendY", ImGuiTableFlags_NoHostExtendY},
249 {"NoKeepColumnsVisible", ImGuiTableFlags_NoKeepColumnsVisible},
250 {"PreciseWidths", ImGuiTableFlags_PreciseWidths},
251 {"NoClip", ImGuiTableFlags_NoClip},
252 {"PadOuterX", ImGuiTableFlags_PadOuterX},
253 {"NoPadOuterX", ImGuiTableFlags_NoPadOuterX},
254 {"NoPadInnerX", ImGuiTableFlags_NoPadInnerX},
255 {"ScrollX", ImGuiTableFlags_ScrollX},
256 {"ScrollY", ImGuiTableFlags_ScrollY},
257 {"SortMulti", ImGuiTableFlags_SortMulti},
258 {"SortTristate", ImGuiTableFlags_SortTristate}};
259 ImGuiTableFlags tableFlags = ImGuiTableFlags_None;
260 for (const auto& flag : flag_tokens) {
261 if (flagMap.find(flag) != flagMap.end()) {
262 tableFlags |= flagMap[flag];
263 }
264 }
265 // Reserve data to the void* pointer and assign flags
266 attributes.flags = std::make_unique<ImGuiTableFlags>(tableFlags);
267 } break;
269 static std::map<std::string, ImGuiTableColumnFlags> flagMap = {
270 {"None", ImGuiTableColumnFlags_None},
271 {"DefaultHide", ImGuiTableColumnFlags_DefaultHide},
272 {"DefaultSort", ImGuiTableColumnFlags_DefaultSort},
273 {"WidthStretch", ImGuiTableColumnFlags_WidthStretch},
274 {"WidthFixed", ImGuiTableColumnFlags_WidthFixed},
275 {"NoResize", ImGuiTableColumnFlags_NoResize},
276 {"NoReorder", ImGuiTableColumnFlags_NoReorder},
277 {"NoHide", ImGuiTableColumnFlags_NoHide},
278 {"NoClip", ImGuiTableColumnFlags_NoClip},
279 {"NoSort", ImGuiTableColumnFlags_NoSort},
280 {"NoSortAscending", ImGuiTableColumnFlags_NoSortAscending},
281 {"NoSortDescending", ImGuiTableColumnFlags_NoSortDescending},
282 {"NoHeaderWidth", ImGuiTableColumnFlags_NoHeaderWidth},
283 {"PreferSortAscending", ImGuiTableColumnFlags_PreferSortAscending},
284 {"PreferSortDescending", ImGuiTableColumnFlags_PreferSortDescending},
285 {"IndentEnable", ImGuiTableColumnFlags_IndentEnable},
286 {"IndentDisable", ImGuiTableColumnFlags_IndentDisable},
287 {"IsEnabled", ImGuiTableColumnFlags_IsEnabled},
288 {"IsVisible", ImGuiTableColumnFlags_IsVisible},
289 {"IsSorted", ImGuiTableColumnFlags_IsSorted},
290 {"IsHovered", ImGuiTableColumnFlags_IsHovered}};
291 ImGuiTableColumnFlags columnFlags = ImGuiTableColumnFlags_None;
292 for (const auto& flag : flag_tokens) {
293 if (flagMap.find(flag) != flagMap.end()) {
294 columnFlags |= flagMap[flag];
295 }
296 }
297 // Reserve data to the void* pointer and assign flags
298 attributes.flags = std::make_unique<ImGuiTableColumnFlags>(columnFlags);
299 }
300 default:
301 break;
302 }
303}
304
306 const std::vector<Token>& tokens, size_t& index, const WidgetType& type,
307 const std::map<std::string, void*>& data_bindings) {
308 WidgetAttributes attributes;
309
310 while (index < tokens.size() && tokens[index].type != TokenType::CloseBrace) {
311 if (tokens[index].type == TokenType::Identifier) {
312 Token keyToken = tokens[index];
313 index++; // Move to the value token.
314 if (index < tokens.size() && tokens[index].type == TokenType::String) {
315 std::string value = tokens[index].value;
316 index++; // Move past the value.
317
318 if (keyToken.value == "id")
319 attributes.id = value;
320 else if (keyToken.value == "title")
321 attributes.title = value;
322 else if (keyToken.value == "min")
323 attributes.min = std::stod(value);
324 else if (keyToken.value == "max")
325 attributes.max = std::stod(value);
326 else if (keyToken.value == "value")
327 attributes.value = std::stod(value);
328 else if (keyToken.value == "width")
329 if (value == "autox")
330 attributes.width = ImGui::GetContentRegionAvail().x;
331 else if (value == "autoy")
332 attributes.width = ImGui::GetContentRegionAvail().y;
333 else
334 attributes.width = std::stod(value);
335 else if (keyToken.value == "text")
336 attributes.text = value;
337 else if (keyToken.value == "data" &&
338 data_bindings.find(value) != data_bindings.end()) {
339 attributes.data = data_bindings.at(value);
340 } else if (keyToken.value == "count") {
341 attributes.count = std::stoi(value);
342 } else if (keyToken.value == "flags") {
343 ParseFlags(type, value, attributes);
344 } else if (keyToken.value == "size") {
345 std::string sizeX, sizeY;
346 std::istringstream sizeStream(value);
347 std::getline(sizeStream, sizeX, ',');
348 std::getline(sizeStream, sizeY, ',');
349 attributes.size = ImVec2(std::stod(sizeX), std::stod(sizeY));
350 }
351 }
352 } else {
353 // If it's not an identifier or we encounter an open brace, break out.
354 break;
355 }
356 }
357 return attributes;
358}
359
360Node Parse(const std::string& yazon_input,
361 const std::map<std::string, void*>& data_bindings) {
362 size_t index = 0;
363 auto tokens = Tokenize(yazon_input);
364
365 std::map<std::string, Node> definitions;
366 if (tokens[index].value == "Definitions") {
367 index++; // Skip the "Definitions" token
368 while (index < tokens.size() &&
369 tokens[index].value != "Layout") { // Skip the definitions
370 // Get the definition name and parse the node
371 std::string definition_name = tokens[index].value;
372 index++; // Move to the definition node
373 definitions[definition_name] = ParseNode(tokens, index, data_bindings);
374 index++;
375 }
376 }
377
378 return ParseNode(tokens, index, data_bindings);
379}
380
381void Render(Node& node) {
382 switch (node.type) {
383 case WidgetType::Window: {
384 ImGuiWindowFlags flags = ImGuiWindowFlags_None;
385 if (node.attributes.flags) {
386 flags = *(ImGuiWindowFlags*)node.attributes.flags.get();
387 }
388 if (ImGui::Begin(node.attributes.title.c_str(), nullptr, flags)) {
389 for (auto& child : node.children) {
390 Render(child);
391 }
392 ImGui::End();
393 }
394 } break;
396 if (node.attributes.data) {
397 // Format the text with the data value
398 char formattedText[256];
399 snprintf(formattedText, sizeof(formattedText),
400 node.attributes.text.c_str(), *(int*)node.attributes.data);
401 if (ImGui::Button(formattedText)) {
403 }
404 } else {
405 if (ImGui::Button(node.attributes.text.c_str())) {
407 }
408 }
409 break;
411 ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_None;
412 if (node.attributes.flags) {
413 flags = *(ImGuiTreeNodeFlags*)node.attributes.flags.get();
414 }
415 if (ImGui::CollapsingHeader(node.attributes.title.c_str(), flags)) {
416 for (auto& child : node.children) {
417 Render(child);
418 }
419 }
420 } break;
422 ImGui::Columns(node.attributes.count, node.attributes.title.c_str());
423 ImGui::Separator();
424 for (auto& child : node.children) {
425 Render(child);
426 ImGui::NextColumn();
427 }
428 ImGui::Columns(1);
429 ImGui::Separator();
430 break;
432 if (ImGui::Checkbox(node.attributes.title.c_str(),
433 (bool*)node.attributes.data)) {
435 }
436 break;
437 case WidgetType::Table: {
438 ImGuiTableFlags flags = ImGuiTableFlags_None;
439 if (node.attributes.flags) {
440 flags = *(ImGuiTableFlags*)node.attributes.flags.get();
441 }
442 if (ImGui::BeginTable(node.attributes.id.c_str(), node.attributes.count,
443 flags)) {
444 for (auto& child : node.children) {
445 Render(child);
446 }
447 }
448 ImGui::EndTable();
449 } break;
451 ImGuiTableColumnFlags flags = ImGuiTableColumnFlags_None;
452 if (node.attributes.flags) {
453 flags = *(ImGuiTableColumnFlags*)node.attributes.flags.get();
454 }
455 ImGui::TableSetupColumn(node.attributes.title.c_str(), flags);
456 } break;
458 ImGui::TableHeadersRow();
459 break;
461 ImGui::TableNextColumn();
462 break;
463 case WidgetType::Text:
464 if (node.attributes.data) {
465 // Assuming all data-bound Text widgets use string formatting
466 char formattedText[128];
467 snprintf(formattedText, sizeof(formattedText),
468 node.attributes.text.c_str(),
469 *(int*)node.attributes.data & 0xFFFF);
470 ImGui::Text("%s", formattedText);
471 } else {
472 ImGui::Text("%s", node.attributes.text.c_str());
473 }
474 break;
476 node.actions[0].callback();
477 break;
478 }
480 if (ImGui::BeginChild(node.attributes.id.c_str(), node.attributes.size)) {
481 for (auto& child : node.children) {
482 Render(child);
483 }
484 ImGui::EndChild();
485 }
486 break;
488 if (ImGui::BeginMenuBar()) {
489 for (auto& child : node.children) {
490 Render(child);
491 }
492 ImGui::EndMenuBar();
493 }
494 break;
496 if (ImGui::BeginMenu(node.attributes.title.c_str())) {
497 for (auto& child : node.children) {
498 Render(child);
499 }
500 ImGui::EndMenu();
501 }
502 break;
503 }
505 if (ImGui::MenuItem(node.attributes.title.c_str())) {
507 }
508 break;
509 }
511 ImGui::Separator();
512 break;
514 if (ImGui::Selectable(node.attributes.title.c_str(),
515 (bool*)node.attributes.selected)) {
517 }
518 break;
520 if (ImGui::BeginTabBar(node.attributes.title.c_str())) {
521 for (auto& child : node.children) {
522 Render(child);
523 }
524 ImGui::EndTabBar();
525 }
526 break;
528 if (ImGui::BeginTabItem(node.attributes.title.c_str())) {
529 for (auto& child : node.children) {
530 Render(child);
531 }
532 ImGui::EndTabItem();
533 }
534 break;
536 gui::InputHexByte(node.attributes.id.c_str(),
537 (uint8_t*)node.attributes.data);
538 break;
540 gui::InputHexWord(node.attributes.id.c_str(),
541 (uint16_t*)node.attributes.data);
542 break;
543 case WidgetType::Canvas: {
544 gui::Canvas* canvas = (gui::Canvas*)node.attributes.data;
545 if (canvas) {
546 canvas->DrawBackground();
547 canvas->DrawContextMenu();
548
549 canvas->DrawGrid();
550 canvas->DrawOverlay();
551 }
552 break;
553 }
554 default:
555 break;
556 }
557}
558
559void ExecuteActions(const std::vector<Action>& actions, ActionType type) {
560 for (const auto& action : actions) {
561 if (action.type == type) {
562 action.callback(); // Execute the callback associated with the action
563 }
564 }
565}
566
567void Bind(Node* node, std::function<void()> callback) {
568 if (node) {
569 Action action = {ActionType::Click, callback};
570 node->actions.push_back(action);
571 }
572}
573
574void BindAction(Node* node, ActionType type, std::function<void()> callback) {
575 if (node) {
576 Action action = {type, callback};
577 node->actions.push_back(action);
578 }
579}
580
581void BindSelectable(Node* node, bool* selected,
582 std::function<void()> callback) {
583 if (node) {
584 Action action = {ActionType::Click, callback};
585 node->actions.push_back(action);
586 node->attributes.selected = selected;
587 }
588}
589
590std::string LoadFile(const std::string& filename) {
591 std::string fileContents;
592 const std::string kPath = "assets/layouts/";
593
594#ifdef __APPLE__
595#if TARGET_OS_IOS == 1
596 const std::string kBundlePath = core::GetBundleResourcePath();
597 std::ifstream file(kBundlePath + filename);
598#else
599 const std::string kBundlePath = core::GetBundleResourcePath();
600 std::ifstream file(kBundlePath + "Contents/Resources/layouts/" + filename);
601#endif
602#else
603 std::ifstream file(kPath + filename);
604#endif
605
606 if (file.is_open()) {
607 std::string line;
608 while (std::getline(file, line)) {
609 fileContents += line;
610 }
611 file.close();
612 } else {
613 fileContents = "File not found: " + filename;
614 std::cout << fileContents << std::endl;
615 }
616 return fileContents;
617}
618
619} // namespace zeml
620} // namespace gui
621} // namespace app
622} // namespace yaze
Represents a canvas for drawing and manipulating graphics.
Definition canvas.h:34
void DrawBackground(ImVec2 canvas_size=ImVec2(0, 0), bool drag=false)
Definition canvas.cc:66
void DrawGrid(float grid_step=64.0f, int tile_id_offset=8)
Definition canvas.cc:686
void DrawContextMenu(gfx::Bitmap *bitmap=nullptr)
Definition canvas.cc:101
std::string GetBundleResourcePath()
GetBundleResourcePath returns the path to the bundle resource directory. Specific to MacOS.
WidgetAttributes ParseAttributes(const std::vector< Token > &tokens, size_t &index, const WidgetType &type, const std::map< std::string, void * > &data_bindings)
ParseNode attributes for a widget.
Definition zeml.cc:305
Node Parse(const std::string &yazon_input, const std::map< std::string, void * > &data_bindings)
Parse a zeml string.
Definition zeml.cc:360
void BindAction(Node *node, ActionType type, std::function< void()> callback)
Bind an action to a node.
Definition zeml.cc:574
void ExecuteActions(const std::vector< Action > &actions, ActionType type)
Execute actions for a node.
Definition zeml.cc:559
void Bind(Node *node, std::function< void()> callback)
Bind a callback to a node.
Definition zeml.cc:567
void BindSelectable(Node *node, bool *selected, std::function< void()> callback)
Bind a selectable node.
Definition zeml.cc:581
void Render(Node &node)
Render a zeml tree.
Definition zeml.cc:381
Node ParseNode(const std::vector< Token > &tokens, size_t &index, const std::map< std::string, void * > &data_bindings, const std::map< std::string, Node > &definitions)
Parse a zeml node.
Definition zeml.cc:87
std::string LoadFile(const std::string &filename)
Definition zeml.cc:590
WidgetType MapType(const std::string &type)
Map a string to a widget type.
Definition zeml.cc:57
void ParseFlags(const WidgetType &type, const std::string &flags, WidgetAttributes &attributes)
Definition zeml.cc:135
std::vector< Token > Tokenize(const std::string &input)
Tokenize a zeml string.
Definition zeml.cc:22
bool InputHexByte(const char *label, uint8_t *data, float input_width, bool no_step)
Definition input.cc:175
bool InputHexWord(const char *label, uint16_t *data, float input_width, bool no_step)
Definition input.cc:161
Definition common.cc:22
Node for a zeml tree.
Definition zeml.h:125
std::vector< Action > actions
Definition zeml.h:128
std::vector< Node > children
Definition zeml.h:129
WidgetAttributes attributes
Definition zeml.h:127
Attributes for a widget.
Definition zeml.h:88
std::shared_ptr< void > flags
Definition zeml.h:99