GuiUtils.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. #include "GuiUtils.h"
  2. void HelpMarker(const char* description) {
  3. ImGui::TextDisabled("(?)");
  4. if (ImGui::IsItemHovered(ImGuiHoveredFlags_DelayShort)) {
  5. ImGui::BeginTooltip();
  6. ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
  7. ImGui::TextUnformatted(description);
  8. ImGui::PopTextWrapPos();
  9. ImGui::EndTooltip();
  10. }
  11. }
  12. void AddUnderLine(ImColor color) {
  13. ImVec2 min = ImGui::GetItemRectMin();
  14. ImVec2 max = ImGui::GetItemRectMax();
  15. min.y = max.y;
  16. ImGui::GetWindowDrawList()->AddLine(min, max, color, 1.0f);
  17. }
  18. void TextURL(const char* name_, const char* URL_, bool SameLineBefore_, bool SameLineAfter_) {
  19. if (SameLineBefore_)
  20. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
  21. ImGui::PushStyleColor(ImGuiCol_Text, ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
  22. ImGui::Text(name_);
  23. ImGui::PopStyleColor();
  24. if (ImGui::IsItemHovered()) {
  25. if (ImGui::IsMouseClicked(0))
  26. ShellExecuteA(0, 0, URL_, 0, 0, SW_SHOW);
  27. AddUnderLine(ImGui::GetStyle().Colors[ImGuiCol_ButtonHovered]);
  28. ImGui::SetTooltip("Open in browser\n%s", URL_);
  29. }
  30. else
  31. AddUnderLine(ImGui::GetStyle().Colors[ImGuiCol_Button]);
  32. if (SameLineAfter_)
  33. ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
  34. }
  35. struct GroupPanelHeaderBounds
  36. {
  37. ImRect left;
  38. ImRect right;
  39. bool collapsed;
  40. };
  41. static ImVector<GroupPanelHeaderBounds> _groupPanelStack;
  42. static bool GroupPanelIsOpen(ImGuiID id)
  43. {
  44. ImGuiContext& g = *GImGui;
  45. ImGuiWindow* window = g.CurrentWindow;
  46. ImGuiStorage* storage = window->DC.StateStorage;
  47. return storage->GetInt(id, 1) != 0;
  48. }
  49. static void GroupPanelSetOpen(ImGuiID id, bool open)
  50. {
  51. ImGuiContext& g = *GImGui;
  52. ImGuiWindow* window = g.CurrentWindow;
  53. ImGuiStorage* storage = window->DC.StateStorage;
  54. storage->SetInt(id, open ? 1 : 0);
  55. }
  56. bool BeginGroupPanel(const char* label, bool node, const ImVec2& size)
  57. {
  58. ImGuiContext& g = *GImGui;
  59. ImGuiWindow* window = g.CurrentWindow;
  60. const ImGuiID id = window->GetID(label);
  61. ImGui::PushID(id);
  62. auto groupPanelPos = window->DC.CursorPos;
  63. auto itemSpacing = ImGui::GetStyle().ItemSpacing;
  64. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
  65. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
  66. ImGui::BeginGroup(); // Outer group
  67. ImVec2 effectiveSize = size;
  68. if (size.x < 0.0f)
  69. effectiveSize.x = ImGui::GetContentRegionAvail().x;
  70. else
  71. effectiveSize.x = size.x;
  72. ImGui::Dummy(ImVec2(effectiveSize.x, 0.0f)); // Adjusting group x size
  73. auto frameHeight = ImGui::GetFrameHeight();
  74. ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); ImGui::SameLine(0.0f, 0.0f); // Inner group spacing
  75. ImGui::BeginGroup(); // Inner group
  76. ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f)); ImGui::SameLine(0.0f, 0.0f); // Name text spacing
  77. ImGui::TextUnformatted(label);
  78. ImRect leftRect = { ImGui::GetItemRectMin(), ImGui::GetItemRectMax() };
  79. ImVec2 rightMax = ImVec2(groupPanelPos.x + effectiveSize.x - frameHeight, leftRect.Max.y);
  80. ImRect rightRect = { { rightMax.x, leftRect.Min.x }, rightMax };
  81. ImGui::SameLine(0.0f, 0.0f);
  82. ImGui::Dummy(ImVec2(0.0, frameHeight + itemSpacing.y));
  83. if (node)
  84. {
  85. leftRect.Min.x = groupPanelPos.x;
  86. const ImVec2 text_size = ImGui::CalcTextSize(label);
  87. bool isOpen = GroupPanelIsOpen(id);
  88. bool hovered;
  89. bool toggled = ImGui::ButtonBehavior(leftRect, id, &hovered, nullptr, ImGuiButtonFlags_PressedOnClick);
  90. if (toggled)
  91. {
  92. isOpen = !isOpen;
  93. GroupPanelSetOpen(id, isOpen);
  94. }
  95. const ImU32 text_col = ImGui::GetColorU32(ImGuiCol_Text);
  96. ImGui::RenderArrow(window->DrawList, { groupPanelPos.x, groupPanelPos.y + text_size.y * 0.15f }, text_col,
  97. isOpen ? ImGuiDir_Down : ImGuiDir_Right, 0.7f);
  98. if (!isOpen)
  99. {
  100. ImGui::PopStyleVar(2);
  101. ImGui::EndGroup();
  102. ImGui::EndGroup();
  103. ImGui::PopID();
  104. _groupPanelStack.push_back({ leftRect, rightRect, true });
  105. return false;
  106. }
  107. }
  108. ImGui::PopStyleVar(2);
  109. ImGui::GetCurrentWindow()->ContentRegionRect.Max.x -= frameHeight * 0.5f;
  110. ImGui::GetCurrentWindow()->WorkRect.Max.x -= frameHeight * 0.5f;
  111. ImGui::GetCurrentWindow()->InnerRect.Max.x -= frameHeight * 0.5f;
  112. ImGui::GetCurrentWindow()->Size.x -= frameHeight;
  113. auto itemWidth = ImGui::CalcItemWidth();
  114. ImGui::PushItemWidth(ImMax(0.0f, itemWidth - frameHeight));
  115. _groupPanelStack.push_back({ leftRect, rightRect, false });
  116. return true;
  117. }
  118. const char* languages[] = { "English", "Russian", "Chinese",
  119. "Indonesian/Not supported at this time", "Romanian"
  120. };
  121. void ConfigComboLanguage(ConfigField<int>& f_Language) {
  122. int currentLanguage = f_Language.getValue();
  123. if (ImGui::Combo(_("LANGUAGE_SELECT"), &currentLanguage, languages, IM_ARRAYSIZE(languages))) {
  124. f_Language.setValue(currentLanguage);
  125. config::setValue(f_Language, currentLanguage);
  126. }
  127. }
  128. void EndGroupPanel() {
  129. IM_ASSERT(_groupPanelStack.Size > 0); // Mismatched BeginGroupPanel()/EndGroupPanel() calls
  130. auto& info = _groupPanelStack.back();
  131. _groupPanelStack.pop_back();
  132. if (info.collapsed)
  133. return;
  134. ImGui::PopItemWidth();
  135. auto itemSpacing = ImGui::GetStyle().ItemSpacing;
  136. ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
  137. ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
  138. ImGui::EndGroup(); // Inner group
  139. auto frameHeight = ImGui::GetFrameHeight();
  140. ImGui::SameLine(0.0f, 0.0f);
  141. ImGui::Dummy(ImVec2(frameHeight * 0.5f, 0.0f));
  142. ImGui::Dummy(ImVec2(0.0, frameHeight - frameHeight * 0.5f - itemSpacing.y));
  143. ImGui::EndGroup(); // Outer group
  144. // Outer group rect
  145. auto itemMin = ImGui::GetItemRectMin();
  146. auto itemMax = ImGui::GetItemRectMax();
  147. ImVec2 halfFrame = ImVec2(frameHeight * 0.25f, frameHeight) * 0.5f;
  148. ImRect frameRect = ImRect(itemMin + halfFrame, itemMax - ImVec2(halfFrame.x, 0.0f));
  149. auto& leftRect = info.left;
  150. leftRect.Min.x -= itemSpacing.x;
  151. leftRect.Max.x += itemSpacing.x;
  152. bool hasRightPart = info.right.Min.x != info.right.Max.x;
  153. auto& rightRect = info.right;
  154. if (hasRightPart) {
  155. rightRect.Min.x -= itemSpacing.x;
  156. rightRect.Max.x += itemSpacing.x;
  157. }
  158. // Drawing rectangle
  159. for (int i = 0; i < (hasRightPart ? 5 : 3); ++i) {
  160. switch (i) {
  161. case 0: // left half-plane
  162. ImGui::PushClipRect(ImVec2(-FLT_MAX, -FLT_MAX), ImVec2(leftRect.Min.x, FLT_MAX), true);
  163. break;
  164. case 1: // right half-plane
  165. ImGui::PushClipRect(ImVec2(leftRect.Max.x, -FLT_MAX), ImVec2(hasRightPart ? rightRect.Min.x : FLT_MAX, FLT_MAX), true);
  166. break;
  167. case 2: // bottom
  168. ImGui::PushClipRect(ImVec2(leftRect.Min.x, leftRect.Max.y), ImVec2(leftRect.Max.x, FLT_MAX), true);
  169. break;
  170. case 3: // bottom select
  171. ImGui::PushClipRect(ImVec2(rightRect.Min.x, rightRect.Max.y), ImVec2(rightRect.Max.x, FLT_MAX), true);
  172. break;
  173. case 4: // right hand-plane
  174. ImGui::PushClipRect(ImVec2(rightRect.Max.x, -FLT_MAX), ImVec2(FLT_MAX, FLT_MAX), true);
  175. break;
  176. }
  177. ImGui::GetWindowDrawList()->AddRect(frameRect.Min, frameRect.Max,
  178. ImColor(ImGui::GetStyleColorVec4(ImGuiCol_Border)), halfFrame.x);
  179. ImGui::PopClipRect();
  180. }
  181. ImGui::PopStyleVar(2);
  182. // Restore content region
  183. ImGui::GetCurrentWindow()->ContentRegionRect.Max.x += frameHeight * 0.5f;
  184. ImGui::GetCurrentWindow()->WorkRect.Max.x += frameHeight * 0.5f;
  185. ImGui::GetCurrentWindow()->InnerRect.Max.x += frameHeight * 0.5f;
  186. ImGui::GetCurrentWindow()->Size.x += frameHeight;
  187. // Add vertical spacing
  188. ImGui::Dummy(ImVec2(0.0f, 0.0f));
  189. ImGui::PopID();
  190. }