yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
style.cc
Go to the documentation of this file.
2#include "util/i18n/tr.h"
3
4#include <algorithm>
5
11#include "imgui/imgui.h"
12#include "imgui/imgui_internal.h"
13#include "util/file_util.h"
14#include "util/log.h"
15
16namespace yaze {
17namespace gui {
18
19namespace {
20Color ParseColor(const std::string& color) {
21 Color result;
22 if (color.size() == 7 && color[0] == '#') {
23 result.red = std::stoi(color.substr(1, 2), nullptr, 16) / 255.0f;
24 result.green = std::stoi(color.substr(3, 2), nullptr, 16) / 255.0f;
25 result.blue = std::stoi(color.substr(5, 2), nullptr, 16) / 255.0f;
26 } else {
27 throw std::invalid_argument("Invalid color format: " + color);
28 }
29 return result;
30}
31} // namespace
32
33void ColorsYaze() {
34 ImGuiStyle* style = &ImGui::GetStyle();
35 ImVec4* colors = style->Colors;
36
37 style->WindowPadding = ImVec2(10.f, 10.f);
38 style->FramePadding = ImVec2(10.f, 2.f);
39 style->CellPadding = ImVec2(4.f, 5.f);
40 style->ItemSpacing = ImVec2(10.f, 5.f);
41 style->ItemInnerSpacing = ImVec2(5.f, 5.f);
42 style->TouchExtraPadding = ImVec2(0.f, 0.f);
43 style->IndentSpacing = 20.f;
44 style->ScrollbarSize = 14.f;
45 style->GrabMinSize = 15.f;
46
47 style->WindowBorderSize = 0.f;
48 style->ChildBorderSize = 1.f;
49 style->PopupBorderSize = 1.f;
50 style->FrameBorderSize = 0.f;
51 style->TabBorderSize = 0.f;
52
53 style->WindowRounding = 0.f;
54 style->ChildRounding = 0.f;
55 style->FrameRounding = 5.f;
56 style->PopupRounding = 0.f;
57 style->ScrollbarRounding = 5.f;
58
59 auto alttpDarkGreen = ImVec4(0.18f, 0.26f, 0.18f, 1.0f);
60 auto alttpMidGreen = ImVec4(0.28f, 0.36f, 0.28f, 1.0f);
61 auto allttpLightGreen = ImVec4(0.36f, 0.45f, 0.36f, 1.0f);
62 auto allttpLightestGreen = ImVec4(0.49f, 0.57f, 0.49f, 1.0f);
63
64 colors[ImGuiCol_MenuBarBg] = alttpDarkGreen;
65 colors[ImGuiCol_TitleBg] = alttpMidGreen;
66
67 colors[ImGuiCol_Header] = alttpDarkGreen;
68 colors[ImGuiCol_HeaderHovered] = allttpLightGreen;
69 colors[ImGuiCol_HeaderActive] = alttpMidGreen;
70
71 colors[ImGuiCol_TitleBgActive] = alttpDarkGreen;
72 colors[ImGuiCol_TitleBgCollapsed] = alttpMidGreen;
73
74 colors[ImGuiCol_Tab] = alttpDarkGreen;
75 colors[ImGuiCol_TabHovered] = alttpMidGreen;
76 colors[ImGuiCol_TabActive] = ImVec4(0.347f, 0.466f, 0.347f, 1.000f);
77
78 colors[ImGuiCol_Button] = alttpMidGreen;
79 colors[ImGuiCol_ButtonHovered] = allttpLightestGreen;
80 colors[ImGuiCol_ButtonActive] = allttpLightGreen;
81
82 colors[ImGuiCol_ScrollbarBg] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
83 colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.36f, 0.45f, 0.36f, 0.30f);
84 colors[ImGuiCol_ScrollbarGrabHovered] = ImVec4(0.36f, 0.45f, 0.36f, 0.40f);
85 colors[ImGuiCol_ScrollbarGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
86
87 colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
88 colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
89 colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.85f);
90 colors[ImGuiCol_ChildBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
91 colors[ImGuiCol_PopupBg] = ImVec4(0.11f, 0.11f, 0.14f, 0.92f);
92 colors[ImGuiCol_Border] = allttpLightGreen;
93 colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
94
95 colors[ImGuiCol_FrameBg] = ImVec4(0.43f, 0.43f, 0.43f, 0.39f);
96 colors[ImGuiCol_FrameBgHovered] = ImVec4(0.28f, 0.36f, 0.28f, 0.40f);
97 colors[ImGuiCol_FrameBgActive] = ImVec4(0.28f, 0.36f, 0.28f, 0.69f);
98
99 colors[ImGuiCol_CheckMark] =
100 ImVec4(0.26f, 0.59f, 0.98f, 1.00f); // Solid blue checkmark
101 colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
102 colors[ImGuiCol_SliderGrabActive] = ImVec4(0.36f, 0.45f, 0.36f, 0.60f);
103
104 colors[ImGuiCol_Separator] = ImVec4(0.50f, 0.50f, 0.50f, 0.60f);
105 colors[ImGuiCol_SeparatorHovered] = ImVec4(0.60f, 0.60f, 0.70f, 1.00f);
106 colors[ImGuiCol_SeparatorActive] = ImVec4(0.70f, 0.70f, 0.90f, 1.00f);
107 colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.10f);
108 colors[ImGuiCol_ResizeGripHovered] = ImVec4(0.78f, 0.82f, 1.00f, 0.60f);
109 colors[ImGuiCol_ResizeGripActive] = ImVec4(0.78f, 0.82f, 1.00f, 0.90f);
110
111 colors[ImGuiCol_TabUnfocused] =
112 ImLerp(colors[ImGuiCol_Tab], colors[ImGuiCol_TitleBg], 0.80f);
113 colors[ImGuiCol_TabUnfocusedActive] =
114 ImLerp(colors[ImGuiCol_TabActive], colors[ImGuiCol_TitleBg], 0.40f);
115 colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
116 colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
117 colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
118 colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
119 colors[ImGuiCol_TableHeaderBg] = alttpDarkGreen;
120 colors[ImGuiCol_TableBorderStrong] = alttpMidGreen;
121 colors[ImGuiCol_TableBorderLight] =
122 ImVec4(0.26f, 0.26f, 0.28f, 1.00f); // Prefer using Alpha=1.0 here
123 colors[ImGuiCol_TableRowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
124 colors[ImGuiCol_TableRowBgAlt] = ImVec4(1.00f, 1.00f, 1.00f, 0.07f);
125 colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
126 colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
127 colors[ImGuiCol_NavHighlight] = colors[ImGuiCol_HeaderHovered];
128 colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
129 colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
130 colors[ImGuiCol_ModalWindowDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
131
132 // ImGui slots and style scalars added after this function was written. They
133 // must be set explicitly: this is the only writer for Classic YAZE, so
134 // anything left out keeps the value of whichever .theme preset was applied
135 // before, and the two greens bleed into a purple docking preview or a cyan
136 // caret. Values mirror BuildClassicYazeTheme's declarations.
137 colors[ImGuiCol_DockingPreview] = ImVec4(0.36f, 0.45f, 0.36f, 0.71f);
138 colors[ImGuiCol_DockingEmptyBg] = alttpDarkGreen;
139 colors[ImGuiCol_InputTextCursor] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
140 colors[ImGuiCol_TextLink] = allttpLightestGreen;
141 colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Separator];
142 colors[ImGuiCol_TabSelectedOverline] = allttpLightestGreen;
143 colors[ImGuiCol_TabDimmedSelectedOverline] = allttpLightestGreen;
144 // Transparent, matching every ImGui built-in style: the drop target is drawn
145 // as an outline (ImGuiCol_DragDropTarget above), not a fill.
146 colors[ImGuiCol_DragDropTargetBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
147 colors[ImGuiCol_UnsavedMarker] = colors[ImGuiCol_Text];
148 style->GrabRounding = 5.f;
149 style->TabRounding = 0.f;
150}
151
152void DrawBitmapViewer(const std::vector<gfx::Bitmap>& bitmaps, float scale,
153 int& current_bitmap_id) {
154 if (bitmaps.empty()) {
155 ImGui::Text(tr("No bitmaps available."));
156 return;
157 }
158
159 // Display the current bitmap index and total count.
160 ImGui::Text(tr("Viewing Bitmap %d / %zu"), current_bitmap_id + 1,
161 bitmaps.size());
162
163 // Buttons to navigate through bitmaps.
164 if (ImGui::Button(tr("<- Prev"))) {
165 if (current_bitmap_id > 0) {
166 --current_bitmap_id;
167 }
168 }
169 ImGui::SameLine();
170 if (ImGui::Button(tr("Next ->"))) {
171 if (current_bitmap_id < bitmaps.size() - 1) {
172 ++current_bitmap_id;
173 }
174 }
175
176 // Display the current bitmap.
177 const gfx::Bitmap& current_bitmap = bitmaps[current_bitmap_id];
178 // Assuming Bitmap has a function to get its texture ID, and width and
179 // height.
180 ImTextureID tex_id = (ImTextureID)(intptr_t)current_bitmap.texture();
181 ImVec2 size(current_bitmap.width() * scale, current_bitmap.height() * scale);
182 // ImGui::Image(tex_id, size);
183
184 // Scroll if the image is larger than the display area.
185 if (ImGui::BeginChild("BitmapScrollArea", ImVec2(0, 0), false,
186 ImGuiWindowFlags_HorizontalScrollbar)) {
187 ImGui::Image(tex_id, size);
188 ImGui::EndChild();
189 }
190}
191
192static const char* const kKeywords[] = {
193 "ADC", "AND", "ASL", "BCC", "BCS", "BEQ", "BIT", "BMI", "BNE", "BPL",
194 "BRA", "BRL", "BVC", "BVS", "CLC", "CLD", "CLI", "CLV", "CMP", "CPX",
195 "CPY", "DEC", "DEX", "DEY", "EOR", "INC", "INX", "INY", "JMP", "JSR",
196 "JSL", "LDA", "LDX", "LDY", "LSR", "MVN", "NOP", "ORA", "PEA", "PER",
197 "PHA", "PHB", "PHD", "PHP", "PHX", "PHY", "PLA", "PLB", "PLD", "PLP",
198 "PLX", "PLY", "REP", "ROL", "ROR", "RTI", "RTL", "RTS", "SBC", "SEC",
199 "SEI", "SEP", "STA", "STP", "STX", "STY", "STZ", "TAX", "TAY", "TCD",
200 "TCS", "TDC", "TRB", "TSB", "TSC", "TSX", "TXA", "TXS", "TXY", "TYA",
201 "TYX", "WAI", "WDM", "XBA", "XCE", "ORG", "LOROM", "HIROM"};
202
203static const char* const kIdentifiers[] = {
204 "abort", "abs", "acos", "asin", "atan", "atexit",
205 "atof", "atoi", "atol", "ceil", "clock", "cosh",
206 "ctime", "div", "exit", "fabs", "floor", "fmod",
207 "getchar", "getenv", "isalnum", "isalpha", "isdigit", "isgraph",
208 "ispunct", "isspace", "isupper", "kbhit", "log10", "log2",
209 "log", "memcmp", "modf", "pow", "putchar", "putenv",
210 "puts", "rand", "remove", "rename", "sinh", "sqrt",
211 "srand", "strcat", "strcmp", "strerror", "time", "tolower",
212 "toupper"};
213
215 TextEditor::LanguageDefinition language_65816;
216 for (auto& k : kKeywords)
217 language_65816.mKeywords.emplace(k);
218
219 for (auto& k : kIdentifiers) {
221 id.mDeclaration = "Built-in function";
222 language_65816.mIdentifiers.insert(std::make_pair(std::string(k), id));
223 }
224
225 language_65816.mTokenRegexStrings.push_back(
226 std::make_pair<std::string, TextEditor::PaletteIndex>(
227 "[ \\t]*#[ \\t]*[a-zA-Z_]+", TextEditor::PaletteIndex::Preprocessor));
228 language_65816.mTokenRegexStrings.push_back(
229 std::make_pair<std::string, TextEditor::PaletteIndex>(
230 "L?\\\"(\\\\.|[^\\\"])*\\\"", TextEditor::PaletteIndex::String));
231 language_65816.mTokenRegexStrings.push_back(
232 std::make_pair<std::string, TextEditor::PaletteIndex>(
233 "\\'\\\\?[^\\']\\'", TextEditor::PaletteIndex::CharLiteral));
234 language_65816.mTokenRegexStrings.push_back(
235 std::make_pair<std::string, TextEditor::PaletteIndex>(
236 "[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)([eE][+-]?[0-9]+)?[fF]?",
238 language_65816.mTokenRegexStrings.push_back(
239 std::make_pair<std::string, TextEditor::PaletteIndex>(
240 "[+-]?[0-9]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
241 language_65816.mTokenRegexStrings.push_back(
242 std::make_pair<std::string, TextEditor::PaletteIndex>(
243 "0[0-7]+[Uu]?[lL]?[lL]?", TextEditor::PaletteIndex::Number));
244 language_65816.mTokenRegexStrings.push_back(
245 std::make_pair<std::string, TextEditor::PaletteIndex>(
246 "0[xX][0-9a-fA-F]+[uU]?[lL]?[lL]?",
248 language_65816.mTokenRegexStrings.push_back(
249 std::make_pair<std::string, TextEditor::PaletteIndex>(
250 "[a-zA-Z_][a-zA-Z0-9_]*", TextEditor::PaletteIndex::Identifier));
251 language_65816.mTokenRegexStrings.push_back(
252 std::make_pair<std::string, TextEditor::PaletteIndex>(
253 "[\\[\\]\\{\\}\\!\\%\\^\\&\\*\\(\\)\\-\\+\\=\\~\\|\\<\\>\\?\\/"
254 "\\;\\,\\.]",
256
257 language_65816.mCommentStart = "/*";
258 language_65816.mCommentEnd = "*/";
259 language_65816.mSingleLineComment = ";";
260
261 language_65816.mCaseSensitive = false;
262 language_65816.mAutoIndentation = true;
263
264 language_65816.mName = "65816";
265
266 return language_65816;
267}
268
269// TODO: Add more display settings to popup windows.
270void BeginWindowWithDisplaySettings(const char* id, bool* active,
271 const ImVec2& size,
272 ImGuiWindowFlags flags) {
273 ImGuiStyle* ref = &ImGui::GetStyle();
274 static float childBgOpacity = 0.75f;
275 auto color = ref->Colors[ImGuiCol_WindowBg];
276
277 ImGui::PushStyleColor(ImGuiCol_WindowBg, color);
278 ImGui::PushStyleColor(ImGuiCol_ChildBg, color);
279 ImGui::PushStyleColor(ImGuiCol_Border, color);
280
281 ImGui::Begin(id, active, flags | ImGuiWindowFlags_MenuBar);
282 ImGui::BeginMenuBar();
283 if (ImGui::BeginMenu(tr("Display Settings"))) {
284 ImGui::SliderFloat(tr("Child Background Opacity"), &childBgOpacity, 0.0f,
285 1.0f);
286 ImGui::EndMenu();
287 }
288 ImGui::EndMenuBar();
289}
290
292 ImGui::End();
293 ImGui::PopStyleColor(3);
294}
295
296void BeginPadding(int i) {
297 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(i, i));
298 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(i, i));
299}
301 EndNoPadding();
302}
303
305 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0, 0));
306 ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
307}
309 ImGui::PopStyleVar(2);
310}
311
312void BeginChildWithScrollbar(const char* str_id) {
313 // Get available region but ensure minimum size for proper scrolling
314 ImVec2 available = ImGui::GetContentRegionAvail();
315 if (available.x < 64.0f)
316 available.x = 64.0f;
317 if (available.y < 64.0f)
318 available.y = 64.0f;
319
320 ImGui::BeginChild(str_id, available, true,
321 ImGuiWindowFlags_AlwaysVerticalScrollbar);
322}
323
324void BeginChildWithScrollbar(const char* str_id, ImVec2 content_size,
325 bool horizontal_scroll) {
326 // Set content size before beginning child to enable proper scrolling.
327 // Allow callers to communicate only one axis when the other should remain
328 // auto-sized by ImGui.
329 if (content_size.x > 0.0f || content_size.y > 0.0f) {
330 ImGui::SetNextWindowContentSize(content_size);
331 }
332
333 // Get available region but ensure minimum size for proper scrolling
334 ImVec2 available = ImGui::GetContentRegionAvail();
335 if (available.x < 64.0f)
336 available.x = 64.0f;
337 if (available.y < 64.0f)
338 available.y = 64.0f;
339
340 ImGui::BeginChild(
341 str_id, available, true,
342 ImGuiWindowFlags_AlwaysVerticalScrollbar |
343 (horizontal_scroll ? ImGuiWindowFlags_AlwaysHorizontalScrollbar : 0));
344}
345
347 ImGuiID child_id = ImGui::GetID((void*)(intptr_t)id);
348 ImGui::BeginChild(child_id, ImGui::GetContentRegionAvail(), true,
349 ImGuiWindowFlags_AlwaysVerticalScrollbar |
350 ImGuiWindowFlags_AlwaysHorizontalScrollbar);
351}
352
353// Helper functions for table canvas management
354void BeginTableCanvas(const char* table_id, int columns, ImVec2 canvas_size) {
355 // Use proper sizing for tables containing canvas elements
356 ImGuiTableFlags flags =
357 ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp;
358
359 // If canvas size is specified, use it as minimum size
360 ImVec2 outer_size = ImVec2(0, 0);
361 if (canvas_size.x > 0 || canvas_size.y > 0) {
362 outer_size = canvas_size;
363 flags |= ImGuiTableFlags_NoHostExtendY; // Prevent auto-extending past
364 // canvas size
365 }
366
367 ImGui::BeginTable(table_id, columns, flags, outer_size);
368}
369
371 ImGui::EndTable();
372}
373
374void SetupCanvasTableColumn(const char* label, float width_ratio) {
375 if (width_ratio > 0) {
376 ImGui::TableSetupColumn(label, ImGuiTableColumnFlags_WidthStretch,
377 width_ratio);
378 } else {
379 ImGui::TableSetupColumn(label, ImGuiTableColumnFlags_WidthStretch);
380 }
381}
382
383void BeginCanvasTableCell(ImVec2 min_size) {
384 ImGui::TableNextColumn();
385
386 // Ensure minimum size for canvas cells
387 if (min_size.x > 0 || min_size.y > 0) {
388 ImVec2 avail = ImGui::GetContentRegionAvail();
389 ImVec2 actual_size =
390 ImVec2(std::max(avail.x, min_size.x), std::max(avail.y, min_size.y));
391
392 // Reserve space for the canvas
393 ImGui::Dummy(actual_size);
394 // ImGui::SetCursorPos(ImGui::GetCursorPos() - actual_size); // Reset cursor
395 // for drawing
396 }
397}
398
399void DrawDisplaySettings(ImGuiStyle* ref) {
400 // You can pass in a reference ImGuiStyle structure to compare to, revert to
401 // and save to (without a reference style pointer, we will use one compared
402 // locally as a reference)
403 ImGuiStyle& style = ImGui::GetStyle();
404 static ImGuiStyle ref_saved_style;
405
406 // Default to using internal storage as reference
407 static bool init = true;
408 if (init && ref == NULL)
409 ref_saved_style = style;
410 init = false;
411 if (ref == NULL)
412 ref = &ref_saved_style;
413
414 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
415
416 // Enhanced theme management section
417 if (ImGui::CollapsingHeader(tr("Theme Management"),
418 ImGuiTreeNodeFlags_DefaultOpen)) {
419 auto& theme_manager = ThemeManager::Get();
420 static bool show_theme_selector = false;
421 static bool show_theme_editor = false;
422
423 ImGui::Text(tr("%s Current Theme:"), ICON_MD_PALETTE);
424 ImGui::SameLine();
425
426 std::string current_theme_name = theme_manager.GetCurrentThemeName();
427 bool is_classic_active = (current_theme_name == "Classic YAZE");
428
429 // Current theme display with color preview
430 if (is_classic_active) {
431 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s",
432 current_theme_name.c_str());
433 } else {
434 ImGui::Text("%s", current_theme_name.c_str());
435 }
436
437 // Theme color preview
438 auto current_theme = theme_manager.GetCurrentTheme();
439 ImGui::SameLine();
440 ImGui::ColorButton("##primary_preview",
441 gui::ConvertColorToImVec4(current_theme.primary),
442 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
443 ImGui::SameLine();
444 ImGui::ColorButton("##secondary_preview",
445 gui::ConvertColorToImVec4(current_theme.secondary),
446 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
447 ImGui::SameLine();
448 ImGui::ColorButton("##accent_preview",
449 gui::ConvertColorToImVec4(current_theme.accent),
450 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
451
452 ImGui::Spacing();
453
454 // Theme selection table for better organization
455 if (ImGui::BeginTable(
456 "ThemeSelectionTable", 3,
457 ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_NoHostExtendY,
458 ImVec2(0, 80))) {
459 ImGui::TableSetupColumn("Built-in", ImGuiTableColumnFlags_WidthStretch,
460 0.3f);
461 ImGui::TableSetupColumn("File Themes", ImGuiTableColumnFlags_WidthStretch,
462 0.4f);
463 ImGui::TableSetupColumn("Actions", ImGuiTableColumnFlags_WidthStretch,
464 0.3f);
465 ImGui::TableHeadersRow();
466
467 ImGui::TableNextRow();
468
469 // Built-in themes column
470 ImGui::TableNextColumn();
471 if (is_classic_active) {
472 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 0.2f, 1.0f));
473 }
474
475 if (ImGui::Button(tr("Classic YAZE"), ImVec2(-1, 30))) {
476 theme_manager.ApplyClassicYazeTheme();
477 ref_saved_style = style;
478 }
479
480 if (is_classic_active) {
481 ImGui::PopStyleColor();
482 }
483
484 if (ImGui::Button(tr("Reset ColorsYaze"), ImVec2(-1, 30))) {
486 ref_saved_style = style;
487 }
488
489 // File themes column
490 ImGui::TableNextColumn();
491 auto available_themes = theme_manager.GetAvailableThemes();
492 const char* current_file_theme = "";
493
494 // Find current file theme for display
495 for (const auto& theme_name : available_themes) {
496 if (theme_name == current_theme_name) {
497 current_file_theme = theme_name.c_str();
498 break;
499 }
500 }
501
502 ImGui::SetNextItemWidth(-1);
503 if (ImGui::BeginCombo("##FileThemes", current_file_theme)) {
504 for (const auto& theme_name : available_themes) {
505 bool is_selected = (theme_name == current_theme_name);
506 if (ImGui::Selectable(theme_name.c_str(), is_selected)) {
507 theme_manager.LoadTheme(theme_name);
508 ref_saved_style = style;
509 }
510 }
511 ImGui::EndCombo();
512 }
513
514 if (ImGui::Button(tr("Refresh Themes"), ImVec2(-1, 30))) {
515 theme_manager.RefreshAvailableThemes();
516 }
517
518 // Actions column
519 ImGui::TableNextColumn();
520 if (ImGui::Button(tr("Theme Selector"), ImVec2(-1, 30))) {
521 show_theme_selector = true;
522 }
523
524 if (ImGui::Button(tr("Theme Editor"), ImVec2(-1, 30))) {
525 show_theme_editor = true;
526 }
527
528 ImGui::EndTable();
529 }
530
531 // Show theme dialogs
532 if (show_theme_selector) {
533 theme_manager.ShowThemeSelector(&show_theme_selector);
534 }
535
536 if (show_theme_editor) {
537 theme_manager.ShowSimpleThemeEditor(&show_theme_editor);
538 }
539 }
540
541 ImGui::Separator();
542
543 // Background effects settings
544 auto& bg_renderer = gui::BackgroundRenderer::Get();
545 bg_renderer.DrawSettingsUI();
546
547 ImGui::Separator();
548
549 if (ImGui::ShowStyleSelector("Colors##Selector"))
550 ref_saved_style = style;
551 ImGui::ShowFontSelector("Fonts##Selector");
552
553 // Simplified Settings (expose floating-pointer border sizes as boolean
554 // representing 0.0f or 1.0f)
555 if (ImGui::SliderFloat(tr("FrameRounding"), &style.FrameRounding, 0.0f, 12.0f,
556 "%.0f"))
557 style.GrabRounding = style.FrameRounding; // Make GrabRounding always the
558 // same value as FrameRounding
559 {
560 bool border = (style.WindowBorderSize > 0.0f);
561 if (ImGui::Checkbox(tr("WindowBorder"), &border)) {
562 style.WindowBorderSize = border ? 1.0f : 0.0f;
563 }
564 }
565 ImGui::SameLine();
566 {
567 bool border = (style.FrameBorderSize > 0.0f);
568 if (ImGui::Checkbox(tr("FrameBorder"), &border)) {
569 style.FrameBorderSize = border ? 1.0f : 0.0f;
570 }
571 }
572 ImGui::SameLine();
573 {
574 bool border = (style.PopupBorderSize > 0.0f);
575 if (ImGui::Checkbox(tr("PopupBorder"), &border)) {
576 style.PopupBorderSize = border ? 1.0f : 0.0f;
577 }
578 }
579
580 // Save/Revert button
581 if (ImGui::Button(tr("Save Ref")))
582 *ref = ref_saved_style = style;
583 ImGui::SameLine();
584 if (ImGui::Button(tr("Revert Ref")))
585 style = *ref;
586 ImGui::SameLine();
587
588 ImGui::Separator();
589
590 if (ImGui::BeginTabBar("##tabs", ImGuiTabBarFlags_None)) {
591 if (ImGui::BeginTabItem(tr("Sizes"))) {
592 ImGui::SeparatorText(tr("Main"));
593 ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f,
594 20.0f, "%.0f");
595 ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f,
596 20.0f, "%.0f");
597 ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f,
598 20.0f, "%.0f");
599 ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing,
600 0.0f, 20.0f, "%.0f");
601 ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding,
602 0.0f, 10.0f, "%.0f");
603 ImGui::SliderFloat(tr("IndentSpacing"), &style.IndentSpacing, 0.0f, 30.0f,
604 "%.0f");
605 ImGui::SliderFloat(tr("ScrollbarSize"), &style.ScrollbarSize, 1.0f, 20.0f,
606 "%.0f");
607 ImGui::SliderFloat(tr("GrabMinSize"), &style.GrabMinSize, 1.0f, 20.0f,
608 "%.0f");
609
610 ImGui::SeparatorText(tr("Borders"));
611 ImGui::SliderFloat(tr("WindowBorderSize"), &style.WindowBorderSize, 0.0f,
612 1.0f, "%.0f");
613 ImGui::SliderFloat(tr("ChildBorderSize"), &style.ChildBorderSize, 0.0f,
614 1.0f, "%.0f");
615 ImGui::SliderFloat(tr("PopupBorderSize"), &style.PopupBorderSize, 0.0f,
616 1.0f, "%.0f");
617 ImGui::SliderFloat(tr("FrameBorderSize"), &style.FrameBorderSize, 0.0f,
618 1.0f, "%.0f");
619 ImGui::SliderFloat(tr("TabBorderSize"), &style.TabBorderSize, 0.0f, 1.0f,
620 "%.0f");
621 ImGui::SliderFloat(tr("TabBarBorderSize"), &style.TabBarBorderSize, 0.0f,
622 2.0f, "%.0f");
623
624 ImGui::SeparatorText(tr("Rounding"));
625 ImGui::SliderFloat(tr("WindowRounding"), &style.WindowRounding, 0.0f,
626 12.0f, "%.0f");
627 ImGui::SliderFloat(tr("ChildRounding"), &style.ChildRounding, 0.0f, 12.0f,
628 "%.0f");
629 ImGui::SliderFloat(tr("FrameRounding"), &style.FrameRounding, 0.0f, 12.0f,
630 "%.0f");
631 ImGui::SliderFloat(tr("PopupRounding"), &style.PopupRounding, 0.0f, 12.0f,
632 "%.0f");
633 ImGui::SliderFloat(tr("ScrollbarRounding"), &style.ScrollbarRounding,
634 0.0f, 12.0f, "%.0f");
635 ImGui::SliderFloat(tr("GrabRounding"), &style.GrabRounding, 0.0f, 12.0f,
636 "%.0f");
637 ImGui::SliderFloat(tr("TabRounding"), &style.TabRounding, 0.0f, 12.0f,
638 "%.0f");
639
640 ImGui::SeparatorText(tr("Tables"));
641 ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f,
642 20.0f, "%.0f");
643 ImGui::SliderAngle("TableAngledHeadersAngle",
644 &style.TableAngledHeadersAngle, -50.0f, +50.0f);
645
646 ImGui::SeparatorText(tr("Widgets"));
647 ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign,
648 0.0f, 1.0f, "%.2f");
649 ImGui::Combo(tr("ColorButtonPosition"), (int*)&style.ColorButtonPosition,
650 "Left\0Right\0");
651 ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign,
652 0.0f, 1.0f, "%.2f");
653 ImGui::SameLine();
654
655 ImGui::SliderFloat2("SelectableTextAlign",
656 (float*)&style.SelectableTextAlign, 0.0f, 1.0f,
657 "%.2f");
658 ImGui::SameLine();
659
660 ImGui::SliderFloat(tr("SeparatorTextBorderSize"),
661 &style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
662 ImGui::SliderFloat2("SeparatorTextAlign",
663 (float*)&style.SeparatorTextAlign, 0.0f, 1.0f,
664 "%.2f");
665 ImGui::SliderFloat2("SeparatorTextPadding",
666 (float*)&style.SeparatorTextPadding, 0.0f, 40.0f,
667 "%.0f");
668 ImGui::SliderFloat(tr("LogSliderDeadzone"), &style.LogSliderDeadzone,
669 0.0f, 12.0f, "%.0f");
670
671 ImGui::SeparatorText(tr("Tooltips"));
672 for (int n = 0; n < 2; n++)
673 if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse"
674 : "HoverFlagsForTooltipNav")) {
675 ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse
676 : &style.HoverFlagsForTooltipNav;
677 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p,
678 ImGuiHoveredFlags_DelayNone);
679 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p,
680 ImGuiHoveredFlags_DelayShort);
681 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p,
682 ImGuiHoveredFlags_DelayNormal);
683 ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p,
684 ImGuiHoveredFlags_Stationary);
685 ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p,
686 ImGuiHoveredFlags_NoSharedDelay);
687 ImGui::TreePop();
688 }
689
690 ImGui::SeparatorText(tr("Misc"));
691 ImGui::SliderFloat2("DisplaySafeAreaPadding",
692 (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f,
693 "%.0f");
694 ImGui::SameLine();
695
696 ImGui::EndTabItem();
697 }
698
699 if (ImGui::BeginTabItem(tr("Colors"))) {
700 static int output_dest = 0;
701 static bool output_only_modified = true;
702 if (ImGui::Button(tr("Export"))) {
703 if (output_dest == 0)
704 ImGui::LogToClipboard();
705 else
706 ImGui::LogToTTY();
707 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
708 for (int i = 0; i < ImGuiCol_COUNT; i++) {
709 const ImVec4& col = style.Colors[i];
710 const char* name = ImGui::GetStyleColorName(i);
711 if (!output_only_modified ||
712 memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
713 ImGui::LogText(
714 "colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, "
715 "%.2ff);" IM_NEWLINE,
716 name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
717 }
718 ImGui::LogFinish();
719 }
720 ImGui::SameLine();
721 ImGui::SetNextItemWidth(120);
722 ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
723 ImGui::SameLine();
724 ImGui::Checkbox(tr("Only Modified Colors"), &output_only_modified);
725
726 static ImGuiTextFilter filter;
727 filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
728
729 static ImGuiColorEditFlags alpha_flags = 0;
730 if (ImGui::RadioButton(tr("Opaque"),
731 alpha_flags == ImGuiColorEditFlags_None)) {
732 alpha_flags = ImGuiColorEditFlags_None;
733 }
734 ImGui::SameLine();
735 if (ImGui::RadioButton(tr("Alpha"),
736 alpha_flags == ImGuiColorEditFlags_AlphaPreview)) {
737 alpha_flags = ImGuiColorEditFlags_AlphaPreview;
738 }
739 ImGui::SameLine();
740 if (ImGui::RadioButton(
741 tr("Both"),
742 alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) {
743 alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
744 }
745 ImGui::SameLine();
746
747 ImGui::SetNextWindowSizeConstraints(
748 ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10),
749 ImVec2(FLT_MAX, FLT_MAX));
750 ImGui::BeginChild("##colors", ImVec2(0, 0),
751 ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened,
752 ImGuiWindowFlags_AlwaysVerticalScrollbar |
753 ImGuiWindowFlags_AlwaysHorizontalScrollbar);
754 ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
755 for (int i = 0; i < ImGuiCol_COUNT; i++) {
756 const char* name = ImGui::GetStyleColorName(i);
757 if (!filter.PassFilter(name))
758 continue;
759 ImGui::PushID(i);
760 ImGui::ColorEdit4("##color", (float*)&style.Colors[i],
761 ImGuiColorEditFlags_AlphaBar | alpha_flags);
762 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) {
763 // Tips: in a real user application, you may want to merge and use
764 // an icon font into the main font, so instead of "Save"/"Revert"
765 // you'd use icons! Read the FAQ and docs/FONTS.md about using icon
766 // fonts. It's really easy and super convenient!
767 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
768 if (ImGui::Button(tr("Save"))) {
769 ref->Colors[i] = style.Colors[i];
770 }
771 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
772 if (ImGui::Button(tr("Revert"))) {
773 style.Colors[i] = ref->Colors[i];
774 }
775 }
776 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
777 ImGui::TextUnformatted(name);
778 ImGui::PopID();
779 }
780 ImGui::PopItemWidth();
781 ImGui::EndChild();
782
783 ImGui::EndTabItem();
784 }
785
786 if (ImGui::BeginTabItem(tr("Fonts"))) {
787 ImGuiIO& io = ImGui::GetIO();
788 ImFontAtlas* atlas = io.Fonts;
789 ImGui::ShowFontAtlas(atlas);
790
791 // Post-baking font scaling. Note that this is NOT the nice way of
792 // scaling fonts, read below. (we enforce hard clamping manually as by
793 // default DragFloat/SliderFloat allows CTRL+Click text to get out of
794 // bounds).
795 const float MIN_SCALE = 0.3f;
796 const float MAX_SCALE = 2.0f;
797
798 static float window_scale = 1.0f;
799 ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
800 if (ImGui::DragFloat(
801 tr("window scale"), &window_scale, 0.005f, MIN_SCALE, MAX_SCALE,
802 "%.2f",
803 ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
804 ImGui::SetWindowFontScale(window_scale);
805 // Global scale is handled by the caller (PopupManager or
806 // SettingsPanel) to enable persistence via UserSettings.
807 ImGui::PopItemWidth();
808
809 ImGui::EndTabItem();
810 }
811
812 if (ImGui::BeginTabItem(tr("Rendering"))) {
813 ImGui::Checkbox(tr("Anti-aliased lines"), &style.AntiAliasedLines);
814 ImGui::SameLine();
815
816 ImGui::Checkbox(tr("Anti-aliased lines use texture"),
817 &style.AntiAliasedLinesUseTex);
818 ImGui::SameLine();
819
820 ImGui::Checkbox(tr("Anti-aliased fill"), &style.AntiAliasedFill);
821 ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
822 ImGui::DragFloat(tr("Curve Tessellation Tolerance"),
823 &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f,
824 "%.2f");
825 if (style.CurveTessellationTol < 0.10f)
826 style.CurveTessellationTol = 0.10f;
827
828 // When editing the "Circle Segment Max Error" value, draw a preview of
829 // its effect on auto-tessellated circles.
830 ImGui::DragFloat(tr("Circle Tessellation Max Error"),
831 &style.CircleTessellationMaxError, 0.005f, 0.10f, 5.0f,
832 "%.2f", ImGuiSliderFlags_AlwaysClamp);
833 const bool show_samples = ImGui::IsItemActive();
834 if (show_samples)
835 ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
836 if (show_samples && ImGui::BeginTooltip()) {
837 ImGui::TextUnformatted(tr("(R = radius, N = number of segments)"));
838 ImGui::Spacing();
839 ImDrawList* draw_list = ImGui::GetWindowDrawList();
840 const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
841 for (int n = 0; n < 8; n++) {
842 const float RAD_MIN = 5.0f;
843 const float RAD_MAX = 70.0f;
844 const float rad =
845 RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
846
847 ImGui::BeginGroup();
848
849 ImGui::Text(tr("R: %.f\nN: %d"), rad,
850 draw_list->_CalcCircleAutoSegmentCount(rad));
851
852 const float canvas_width = std::max(min_widget_width, rad * 2.0f);
853 const float offset_x = floorf(canvas_width * 0.5f);
854 const float offset_y = floorf(RAD_MAX);
855
856 const ImVec2 p1 = ImGui::GetCursorScreenPos();
857 draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad,
858 ImGui::GetColorU32(ImGuiCol_Text));
859 ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
860
861 /*
862 const ImVec2 p2 = ImGui::GetCursorScreenPos();
863 draw_list->AddCircleFilled(ImVec2(p2.x + offset_x, p2.y + offset_y),
864 rad, ImGui::GetColorU32(ImGuiCol_Text));
865 ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
866 */
867
868 ImGui::EndGroup();
869 ImGui::SameLine();
870 }
871 ImGui::EndTooltip();
872 }
873 ImGui::SameLine();
874
875 ImGui::DragFloat(tr("Global Alpha"), &style.Alpha, 0.005f, 0.20f, 1.0f,
876 "%.2f"); // Not exposing zero here so user doesn't
877 // "lose" the UI (zero alpha clips all
878 // widgets). But application code could have a
879 // toggle to switch between zero and non-zero.
880 ImGui::DragFloat(tr("Disabled Alpha"), &style.DisabledAlpha, 0.005f, 0.0f,
881 1.0f, "%.2f");
882 ImGui::SameLine();
883
884 ImGui::PopItemWidth();
885
886 ImGui::EndTabItem();
887 }
888
889 ImGui::EndTabBar();
890 }
891
892 ImGui::PopItemWidth();
893}
894
895void DrawDisplaySettingsForPopup(ImGuiStyle* ref) {
896 // Popup-safe version of DrawDisplaySettings without problematic tables
897 ImGuiStyle& style = ImGui::GetStyle();
898 static ImGuiStyle ref_saved_style;
899
900 // Default to using internal storage as reference
901 static bool init = true;
902 if (init && ref == NULL)
903 ref_saved_style = style;
904 init = false;
905 if (ref == NULL)
906 ref = &ref_saved_style;
907
908 ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
909
910 // Enhanced theme management section (simplified for popup)
911 if (ImGui::CollapsingHeader(tr("Theme Management"),
912 ImGuiTreeNodeFlags_DefaultOpen)) {
913 auto& theme_manager = ThemeManager::Get();
914
915 ImGui::Text(tr("%s Current Theme:"), ICON_MD_PALETTE);
916 ImGui::SameLine();
917
918 std::string current_theme_name = theme_manager.GetCurrentThemeName();
919 bool is_classic_active = (current_theme_name == "Classic YAZE");
920
921 // Current theme display with color preview
922 if (is_classic_active) {
923 ImGui::TextColored(ImVec4(0.2f, 0.8f, 0.2f, 1.0f), "%s",
924 current_theme_name.c_str());
925 } else {
926 ImGui::Text("%s", current_theme_name.c_str());
927 }
928
929 // Theme color preview
930 auto current_theme = theme_manager.GetCurrentTheme();
931 ImGui::SameLine();
932 ImGui::ColorButton("##primary_preview",
933 gui::ConvertColorToImVec4(current_theme.primary),
934 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
935 ImGui::SameLine();
936 ImGui::ColorButton("##secondary_preview",
937 gui::ConvertColorToImVec4(current_theme.secondary),
938 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
939 ImGui::SameLine();
940 ImGui::ColorButton("##accent_preview",
941 gui::ConvertColorToImVec4(current_theme.accent),
942 ImGuiColorEditFlags_NoTooltip, ImVec2(20, 20));
943
944 ImGui::Spacing();
945
946 // Simplified theme selection (no table to avoid popup conflicts)
947 if (is_classic_active) {
948 ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.2f, 0.6f, 0.2f, 1.0f));
949 }
950
951 if (ImGui::Button(tr("Classic YAZE"))) {
952 theme_manager.ApplyClassicYazeTheme();
953 ref_saved_style = style;
954 }
955
956 if (is_classic_active) {
957 ImGui::PopStyleColor();
958 }
959
960 ImGui::SameLine();
961 if (ImGui::Button(tr("Reset ColorsYaze"))) {
963 ref_saved_style = style;
964 }
965
966 // File themes dropdown
967 auto available_themes = theme_manager.GetAvailableThemes();
968 const char* current_file_theme = "";
969
970 // Find current file theme for display
971 for (const auto& theme_name : available_themes) {
972 if (theme_name == current_theme_name) {
973 current_file_theme = theme_name.c_str();
974 break;
975 }
976 }
977
978 ImGui::Text(tr("File Themes:"));
979 ImGui::SetNextItemWidth(-1);
980 if (ImGui::BeginCombo("##FileThemes", current_file_theme)) {
981 for (const auto& theme_name : available_themes) {
982 bool is_selected = (theme_name == current_theme_name);
983 if (ImGui::Selectable(theme_name.c_str(), is_selected)) {
984 theme_manager.LoadTheme(theme_name);
985 ref_saved_style = style;
986 }
987 }
988 ImGui::EndCombo();
989 }
990
991 if (ImGui::Button(tr("Refresh Themes"))) {
992 theme_manager.RefreshAvailableThemes();
993 }
994 ImGui::SameLine();
995 if (ImGui::Button(tr("Open Theme Editor"))) {
996 static bool show_theme_editor = true;
997 theme_manager.ShowSimpleThemeEditor(&show_theme_editor);
998 }
999 }
1000
1001 ImGui::Separator();
1002
1003 // Background effects settings
1004 auto& bg_renderer = gui::BackgroundRenderer::Get();
1005 bg_renderer.DrawSettingsUI();
1006
1007 ImGui::Separator();
1008
1009 if (ImGui::ShowStyleSelector("Colors##Selector"))
1010 ref_saved_style = style;
1011 ImGui::ShowFontSelector("Fonts##Selector");
1012
1013 // Quick style controls before the tabbed section
1014 if (ImGui::SliderFloat(tr("FrameRounding"), &style.FrameRounding, 0.0f, 12.0f,
1015 "%.0f"))
1016 style.GrabRounding = style.FrameRounding;
1017
1018 // Border checkboxes (simplified layout)
1019 bool window_border = (style.WindowBorderSize > 0.0f);
1020 if (ImGui::Checkbox(tr("WindowBorder"), &window_border)) {
1021 style.WindowBorderSize = window_border ? 1.0f : 0.0f;
1022 }
1023 ImGui::SameLine();
1024
1025 bool frame_border = (style.FrameBorderSize > 0.0f);
1026 if (ImGui::Checkbox(tr("FrameBorder"), &frame_border)) {
1027 style.FrameBorderSize = frame_border ? 1.0f : 0.0f;
1028 }
1029 ImGui::SameLine();
1030
1031 bool popup_border = (style.PopupBorderSize > 0.0f);
1032 if (ImGui::Checkbox(tr("PopupBorder"), &popup_border)) {
1033 style.PopupBorderSize = popup_border ? 1.0f : 0.0f;
1034 }
1035
1036 // Save/Revert buttons
1037 if (ImGui::Button(tr("Save Ref")))
1038 *ref = ref_saved_style = style;
1039 ImGui::SameLine();
1040 if (ImGui::Button(tr("Revert Ref")))
1041 style = *ref;
1042
1043 ImGui::Separator();
1044
1045 // Add the comprehensive tabbed settings from the original DrawDisplaySettings
1046 if (ImGui::BeginTabBar("DisplaySettingsTabs", ImGuiTabBarFlags_None)) {
1047 if (ImGui::BeginTabItem(tr("Sizes"))) {
1048 ImGui::SeparatorText(tr("Main"));
1049 ImGui::SliderFloat2("WindowPadding", (float*)&style.WindowPadding, 0.0f,
1050 20.0f, "%.0f");
1051 ImGui::SliderFloat2("FramePadding", (float*)&style.FramePadding, 0.0f,
1052 20.0f, "%.0f");
1053 ImGui::SliderFloat2("ItemSpacing", (float*)&style.ItemSpacing, 0.0f,
1054 20.0f, "%.0f");
1055 ImGui::SliderFloat2("ItemInnerSpacing", (float*)&style.ItemInnerSpacing,
1056 0.0f, 20.0f, "%.0f");
1057 ImGui::SliderFloat2("TouchExtraPadding", (float*)&style.TouchExtraPadding,
1058 0.0f, 10.0f, "%.0f");
1059 ImGui::SliderFloat(tr("IndentSpacing"), &style.IndentSpacing, 0.0f, 30.0f,
1060 "%.0f");
1061 ImGui::SliderFloat(tr("ScrollbarSize"), &style.ScrollbarSize, 1.0f, 20.0f,
1062 "%.0f");
1063 ImGui::SliderFloat(tr("GrabMinSize"), &style.GrabMinSize, 1.0f, 20.0f,
1064 "%.0f");
1065
1066 ImGui::SeparatorText(tr("Borders"));
1067 ImGui::SliderFloat(tr("WindowBorderSize"), &style.WindowBorderSize, 0.0f,
1068 1.0f, "%.0f");
1069 ImGui::SliderFloat(tr("ChildBorderSize"), &style.ChildBorderSize, 0.0f,
1070 1.0f, "%.0f");
1071 ImGui::SliderFloat(tr("PopupBorderSize"), &style.PopupBorderSize, 0.0f,
1072 1.0f, "%.0f");
1073 ImGui::SliderFloat(tr("FrameBorderSize"), &style.FrameBorderSize, 0.0f,
1074 1.0f, "%.0f");
1075 ImGui::SliderFloat(tr("TabBorderSize"), &style.TabBorderSize, 0.0f, 1.0f,
1076 "%.0f");
1077 ImGui::SliderFloat(tr("TabBarBorderSize"), &style.TabBarBorderSize, 0.0f,
1078 2.0f, "%.0f");
1079
1080 ImGui::SeparatorText(tr("Rounding"));
1081 ImGui::SliderFloat(tr("WindowRounding"), &style.WindowRounding, 0.0f,
1082 12.0f, "%.0f");
1083 ImGui::SliderFloat(tr("ChildRounding"), &style.ChildRounding, 0.0f, 12.0f,
1084 "%.0f");
1085 ImGui::SliderFloat(tr("FrameRounding"), &style.FrameRounding, 0.0f, 12.0f,
1086 "%.0f");
1087 ImGui::SliderFloat(tr("PopupRounding"), &style.PopupRounding, 0.0f, 12.0f,
1088 "%.0f");
1089 ImGui::SliderFloat(tr("ScrollbarRounding"), &style.ScrollbarRounding,
1090 0.0f, 12.0f, "%.0f");
1091 ImGui::SliderFloat(tr("GrabRounding"), &style.GrabRounding, 0.0f, 12.0f,
1092 "%.0f");
1093 ImGui::SliderFloat(tr("TabRounding"), &style.TabRounding, 0.0f, 12.0f,
1094 "%.0f");
1095
1096 ImGui::SeparatorText(tr("Tables"));
1097 ImGui::SliderFloat2("CellPadding", (float*)&style.CellPadding, 0.0f,
1098 20.0f, "%.0f");
1099 ImGui::SliderAngle("TableAngledHeadersAngle",
1100 &style.TableAngledHeadersAngle, -50.0f, +50.0f);
1101
1102 ImGui::SeparatorText(tr("Widgets"));
1103 ImGui::SliderFloat2("WindowTitleAlign", (float*)&style.WindowTitleAlign,
1104 0.0f, 1.0f, "%.2f");
1105 ImGui::Combo(tr("ColorButtonPosition"), (int*)&style.ColorButtonPosition,
1106 "Left\0Right\0");
1107 ImGui::SliderFloat2("ButtonTextAlign", (float*)&style.ButtonTextAlign,
1108 0.0f, 1.0f, "%.2f");
1109 ImGui::SameLine();
1110
1111 ImGui::SliderFloat2("SelectableTextAlign",
1112 (float*)&style.SelectableTextAlign, 0.0f, 1.0f,
1113 "%.2f");
1114 ImGui::SameLine();
1115
1116 ImGui::SliderFloat(tr("SeparatorTextBorderSize"),
1117 &style.SeparatorTextBorderSize, 0.0f, 10.0f, "%.0f");
1118 ImGui::SliderFloat2("SeparatorTextAlign",
1119 (float*)&style.SeparatorTextAlign, 0.0f, 1.0f,
1120 "%.2f");
1121 ImGui::SliderFloat2("SeparatorTextPadding",
1122 (float*)&style.SeparatorTextPadding, 0.0f, 40.0f,
1123 "%.0f");
1124 ImGui::SliderFloat(tr("LogSliderDeadzone"), &style.LogSliderDeadzone,
1125 0.0f, 12.0f, "%.0f");
1126
1127 ImGui::SeparatorText(tr("Tooltips"));
1128 for (int n = 0; n < 2; n++)
1129 if (ImGui::TreeNodeEx(n == 0 ? "HoverFlagsForTooltipMouse"
1130 : "HoverFlagsForTooltipNav")) {
1131 ImGuiHoveredFlags* p = (n == 0) ? &style.HoverFlagsForTooltipMouse
1132 : &style.HoverFlagsForTooltipNav;
1133 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNone", p,
1134 ImGuiHoveredFlags_DelayNone);
1135 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayShort", p,
1136 ImGuiHoveredFlags_DelayShort);
1137 ImGui::CheckboxFlags("ImGuiHoveredFlags_DelayNormal", p,
1138 ImGuiHoveredFlags_DelayNormal);
1139 ImGui::CheckboxFlags("ImGuiHoveredFlags_Stationary", p,
1140 ImGuiHoveredFlags_Stationary);
1141 ImGui::CheckboxFlags("ImGuiHoveredFlags_NoSharedDelay", p,
1142 ImGuiHoveredFlags_NoSharedDelay);
1143 ImGui::TreePop();
1144 }
1145
1146 ImGui::SeparatorText(tr("Misc"));
1147 ImGui::SliderFloat2("DisplaySafeAreaPadding",
1148 (float*)&style.DisplaySafeAreaPadding, 0.0f, 30.0f,
1149 "%.0f");
1150 ImGui::SameLine();
1151
1152 ImGui::EndTabItem();
1153 }
1154
1155 if (ImGui::BeginTabItem(tr("Colors"))) {
1156 static int output_dest = 0;
1157 static bool output_only_modified = true;
1158 if (ImGui::Button(tr("Export"))) {
1159 if (output_dest == 0)
1160 ImGui::LogToClipboard();
1161 else
1162 ImGui::LogToTTY();
1163 ImGui::LogText("ImVec4* colors = ImGui::GetStyle().Colors;" IM_NEWLINE);
1164 for (int i = 0; i < ImGuiCol_COUNT; i++) {
1165 const ImVec4& col = style.Colors[i];
1166 const char* name = ImGui::GetStyleColorName(i);
1167 if (!output_only_modified ||
1168 memcmp(&col, &ref->Colors[i], sizeof(ImVec4)) != 0)
1169 ImGui::LogText(
1170 "colors[ImGuiCol_%s]%*s= ImVec4(%.2ff, %.2ff, %.2ff, "
1171 "%.2ff);" IM_NEWLINE,
1172 name, 23 - (int)strlen(name), "", col.x, col.y, col.z, col.w);
1173 }
1174 ImGui::LogFinish();
1175 }
1176 ImGui::SameLine();
1177 ImGui::SetNextItemWidth(120);
1178 ImGui::Combo("##output_type", &output_dest, "To Clipboard\0To TTY\0");
1179 ImGui::SameLine();
1180 ImGui::Checkbox(tr("Only Modified Colors"), &output_only_modified);
1181
1182 static ImGuiTextFilter filter;
1183 filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
1184
1185 static ImGuiColorEditFlags alpha_flags = 0;
1186 if (ImGui::RadioButton(tr("Opaque"),
1187 alpha_flags == ImGuiColorEditFlags_None)) {
1188 alpha_flags = ImGuiColorEditFlags_None;
1189 }
1190 ImGui::SameLine();
1191 if (ImGui::RadioButton(tr("Alpha"),
1192 alpha_flags == ImGuiColorEditFlags_AlphaPreview)) {
1193 alpha_flags = ImGuiColorEditFlags_AlphaPreview;
1194 }
1195 ImGui::SameLine();
1196 if (ImGui::RadioButton(
1197 tr("Both"),
1198 alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf)) {
1199 alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
1200 }
1201 ImGui::SameLine();
1202
1203 ImGui::SetNextWindowSizeConstraints(
1204 ImVec2(0.0f, ImGui::GetTextLineHeightWithSpacing() * 10),
1205 ImVec2(FLT_MAX, FLT_MAX));
1206 ImGui::BeginChild("##colors", ImVec2(0, 0),
1207 ImGuiChildFlags_Borders | ImGuiChildFlags_NavFlattened,
1208 ImGuiWindowFlags_AlwaysVerticalScrollbar |
1209 ImGuiWindowFlags_AlwaysHorizontalScrollbar);
1210 ImGui::PushItemWidth(ImGui::GetFontSize() * -12);
1211 for (int i = 0; i < ImGuiCol_COUNT; i++) {
1212 const char* name = ImGui::GetStyleColorName(i);
1213 if (!filter.PassFilter(name))
1214 continue;
1215 ImGui::PushID(i);
1216 ImGui::ColorEdit4("##color", (float*)&style.Colors[i],
1217 ImGuiColorEditFlags_AlphaBar | alpha_flags);
1218 if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0) {
1219 // Tips: in a real user application, you may want to merge and use
1220 // an icon font into the main font, so instead of "Save"/"Revert"
1221 // you'd use icons! Read the FAQ and docs/FONTS.md about using icon
1222 // fonts. It's really easy and super convenient!
1223 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1224 if (ImGui::Button(tr("Save"))) {
1225 ref->Colors[i] = style.Colors[i];
1226 }
1227 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1228 if (ImGui::Button(tr("Revert"))) {
1229 style.Colors[i] = ref->Colors[i];
1230 }
1231 }
1232 ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
1233 ImGui::TextUnformatted(name);
1234 ImGui::PopID();
1235 }
1236 ImGui::PopItemWidth();
1237 ImGui::EndChild();
1238
1239 ImGui::EndTabItem();
1240 }
1241
1242 if (ImGui::BeginTabItem(tr("Fonts"))) {
1243 ImGuiIO& io = ImGui::GetIO();
1244 ImFontAtlas* atlas = io.Fonts;
1245 ImGui::ShowFontAtlas(atlas);
1246
1247 // Post-baking font scaling. Note that this is NOT the nice way of
1248 // scaling fonts, read below. (we enforce hard clamping manually as by
1249 // default DragFloat/SliderFloat allows CTRL+Click text to get out of
1250 // bounds).
1251 const float MIN_SCALE = 0.3f;
1252 const float MAX_SCALE = 2.0f;
1253
1254 static float window_scale = 1.0f;
1255 ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
1256 if (ImGui::DragFloat(
1257 tr("window scale"), &window_scale, 0.005f, MIN_SCALE, MAX_SCALE,
1258 "%.2f",
1259 ImGuiSliderFlags_AlwaysClamp)) // Scale only this window
1260 ImGui::SetWindowFontScale(window_scale);
1261 // Global scale is handled by the caller (PopupManager or
1262 // SettingsPanel) to enable persistence via UserSettings.
1263 ImGui::PopItemWidth();
1264
1265 ImGui::EndTabItem();
1266 }
1267
1268 if (ImGui::BeginTabItem(tr("Rendering"))) {
1269 ImGui::Checkbox(tr("Anti-aliased lines"), &style.AntiAliasedLines);
1270 ImGui::SameLine();
1271
1272 ImGui::Checkbox(tr("Anti-aliased lines use texture"),
1273 &style.AntiAliasedLinesUseTex);
1274 ImGui::SameLine();
1275
1276 ImGui::Checkbox(tr("Anti-aliased fill"), &style.AntiAliasedFill);
1277 ImGui::PushItemWidth(ImGui::GetFontSize() * 8);
1278 ImGui::DragFloat(tr("Curve Tessellation Tolerance"),
1279 &style.CurveTessellationTol, 0.02f, 0.10f, 10.0f,
1280 "%.2f");
1281 if (style.CurveTessellationTol < 0.10f)
1282 style.CurveTessellationTol = 0.10f;
1283
1284 // When editing the "Circle Segment Max Error" value, draw a preview of
1285 // its effect on auto-tessellated circles.
1286 ImGui::DragFloat(tr("Circle Tessellation Max Error"),
1287 &style.CircleTessellationMaxError, 0.005f, 0.10f, 5.0f,
1288 "%.2f", ImGuiSliderFlags_AlwaysClamp);
1289 const bool show_samples = ImGui::IsItemActive();
1290 if (show_samples)
1291 ImGui::SetNextWindowPos(ImGui::GetCursorScreenPos());
1292 if (show_samples && ImGui::BeginTooltip()) {
1293 ImGui::TextUnformatted(tr("(R = radius, N = number of segments)"));
1294 ImGui::Spacing();
1295 ImDrawList* draw_list = ImGui::GetWindowDrawList();
1296 const float min_widget_width = ImGui::CalcTextSize("N: MMM\nR: MMM").x;
1297 for (int n = 0; n < 8; n++) {
1298 const float RAD_MIN = 5.0f;
1299 const float RAD_MAX = 70.0f;
1300 const float rad =
1301 RAD_MIN + (RAD_MAX - RAD_MIN) * (float)n / (8.0f - 1.0f);
1302
1303 ImGui::BeginGroup();
1304
1305 ImGui::Text(tr("R: %.f\nN: %d"), rad,
1306 draw_list->_CalcCircleAutoSegmentCount(rad));
1307
1308 const float canvas_width = std::max(min_widget_width, rad * 2.0f);
1309 const float offset_x = floorf(canvas_width * 0.5f);
1310 const float offset_y = floorf(RAD_MAX);
1311
1312 const ImVec2 p1 = ImGui::GetCursorScreenPos();
1313 draw_list->AddCircle(ImVec2(p1.x + offset_x, p1.y + offset_y), rad,
1314 ImGui::GetColorU32(ImGuiCol_Text));
1315 ImGui::Dummy(ImVec2(canvas_width, RAD_MAX * 2));
1316
1317 ImGui::EndGroup();
1318 ImGui::SameLine();
1319 }
1320 ImGui::EndTooltip();
1321 }
1322 ImGui::SameLine();
1323
1324 ImGui::DragFloat(tr("Global Alpha"), &style.Alpha, 0.005f, 0.20f, 1.0f,
1325 "%.2f"); // Not exposing zero here so user doesn't
1326 // "lose" the UI (zero alpha clips all
1327 // widgets). But application code could have a
1328 // toggle to switch between zero and non-zero.
1329 ImGui::DragFloat(tr("Disabled Alpha"), &style.DisabledAlpha, 0.005f, 0.0f,
1330 1.0f, "%.2f");
1331 ImGui::SameLine();
1332
1333 ImGui::PopItemWidth();
1334
1335 ImGui::EndTabItem();
1336 }
1337
1338 ImGui::EndTabBar();
1339 }
1340
1341 ImGui::PopItemWidth();
1342}
1343
1344void TextWithSeparators(const absl::string_view& text) {
1345 ImGui::Separator();
1346 ImGui::Text("%s", text.data());
1347 ImGui::Separator();
1348}
1349
1351 ImGuiIO& io = ImGui::GetIO();
1352 ImFontAtlas* atlas = io.Fonts;
1353
1354 static ImFont* current_font = atlas->Fonts[0];
1355 static int current_font_index = 0;
1356 static int font_size = 16;
1357 static bool font_selected = false;
1358
1359 ImGui::Text(tr("Loaded fonts"));
1360 for (const auto& loaded_font : font_registry.fonts) {
1361 ImGui::Text("%s", loaded_font.font_path);
1362 }
1363 ImGui::Separator();
1364
1365 ImGui::Text(tr("Current Font: %s"), current_font->GetDebugName());
1366 ImGui::Text(tr("Font Size: %d"), font_size);
1367
1368 if (ImGui::BeginCombo(tr("Fonts"), current_font->GetDebugName())) {
1369 for (int i = 0; i < atlas->Fonts.Size; i++) {
1370 bool is_selected = (current_font == atlas->Fonts[i]);
1371 if (ImGui::Selectable(atlas->Fonts[i]->GetDebugName(), is_selected)) {
1372 current_font = atlas->Fonts[i];
1373 current_font_index = i;
1374 font_selected = true;
1375 }
1376 if (is_selected) {
1377 ImGui::SetItemDefaultFocus();
1378 }
1379 }
1380 ImGui::EndCombo();
1381 }
1382
1383 ImGui::Separator();
1384 if (ImGui::SliderInt(tr("Font Size"), &font_size, 8, 32)) {
1385 current_font->Scale = font_size / 16.0f;
1386 }
1387}
1388
1389} // namespace gui
1390} // namespace yaze
Represents a bitmap image optimized for SNES ROM hacking.
Definition bitmap.h:69
TextureHandle texture() const
Definition bitmap.h:403
int height() const
Definition bitmap.h:397
int width() const
Definition bitmap.h:396
static BackgroundRenderer & Get()
static ThemeManager & Get()
#define ICON_MD_PALETTE
Definition icons.h:1370
Color ParseColor(const std::string &color)
Definition style.cc:20
void DrawBitmapViewer(const std::vector< gfx::Bitmap > &bitmaps, float scale, int &current_bitmap_id)
Definition style.cc:152
void BeginCanvasTableCell(ImVec2 min_size)
Definition style.cc:383
ImVec4 ConvertColorToImVec4(const Color &color)
Definition color.h:134
void BeginTableCanvas(const char *table_id, int columns, ImVec2 canvas_size)
Definition style.cc:354
void DrawFontManager()
Definition style.cc:1350
void BeginPadding(int i)
Definition style.cc:296
void BeginChildBothScrollbars(int id)
Definition style.cc:346
void EndNoPadding()
Definition style.cc:308
TextEditor::LanguageDefinition GetAssemblyLanguageDef()
Definition style.cc:214
void DrawDisplaySettings(ImGuiStyle *ref)
Definition style.cc:399
void EndPadding()
Definition style.cc:300
void BeginNoPadding()
Definition style.cc:304
void SetupCanvasTableColumn(const char *label, float width_ratio)
Definition style.cc:374
void EndWindowWithDisplaySettings()
Definition style.cc:291
void DrawDisplaySettingsForPopup(ImGuiStyle *ref)
Definition style.cc:895
void EndTableCanvas()
Definition style.cc:370
void ColorsYaze()
Definition style.cc:33
void BeginWindowWithDisplaySettings(const char *id, bool *active, const ImVec2 &size, ImGuiWindowFlags flags)
Definition style.cc:270
void TextWithSeparators(const absl::string_view &text)
Definition style.cc:1344
void BeginChildWithScrollbar(const char *str_id)
Definition style.cc:312
FontState font_registry
Definition font_loader.h:23
TokenRegexStrings mTokenRegexStrings
std::vector< FontConfig > fonts
Definition font_loader.h:20
float green
Definition color.h:18