demo_widgets.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. // Part of ImGui Bundle - MIT License - Copyright (c) 2022-2026 Pascal Thomet - https://github.com/pthom/imgui_bundle
  2. #include "hello_imgui/hello_imgui.h"
  3. #include "hello_imgui/icons_font_awesome_4.h"
  4. #include "imspinner/imspinner.h"
  5. #include "imgui_toggle/imgui_toggle.h"
  6. #include "imgui_toggle/imgui_toggle_presets.h"
  7. #include "imgui_toggle/imgui_toggle_palette.h"
  8. #include "imgui_toggle/imgui_toggle_renderer.h"
  9. #include "immapp/immapp.h"
  10. #include "portable_file_dialogs/portable_file_dialogs.h"
  11. #include "imgui-command-palette/imcmd_command_palette.h"
  12. #include "imgui-knobs/imgui-knobs.h"
  13. #include "ImGuiColorTextEdit/TextEditor.h"
  14. #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG
  15. #include "ImFileDialog/ImFileDialog.h"
  16. #endif
  17. #include "imgui_md_wrapper.h"
  18. #include "ImCoolBar/ImCoolBar.h"
  19. #include "demo_utils/api_demos.h"
  20. #include <fplus/fplus.hpp>
  21. #include <memory>
  22. void DemoKnobs()
  23. {
  24. ImGuiMd::RenderUnindented(R"(
  25. # Knobs
  26. [imgui-knobs](https://github.com/altschuler/imgui-knobs) provides knobs for ImGui.
  27. )");
  28. static float knob_float_value = 0.f;
  29. static int knob_int_value = 0;
  30. std::vector<std::pair<ImGuiKnobVariant, std::string>> knob_types = {
  31. {ImGuiKnobVariant_Tick, "tick"},
  32. {ImGuiKnobVariant_Dot, "dot"},
  33. {ImGuiKnobVariant_Space, "space"},
  34. {ImGuiKnobVariant_Stepped, "stepped"},
  35. {ImGuiKnobVariant_Wiper, "wiper"},
  36. {ImGuiKnobVariant_WiperDot, "wiper_dot"},
  37. {ImGuiKnobVariant_WiperOnly, "wiper_only"},
  38. };
  39. auto show_float_knobs = [&knob_types](float knob_size)
  40. {
  41. std::string knob_size_str = std::to_string(knob_size);
  42. ImGui::PushID((knob_size_str + "_float").c_str());
  43. for (const auto& [knob_type, knob_typename] : knob_types)
  44. {
  45. ImGuiKnobs::Knob(
  46. knob_typename.c_str(),
  47. &knob_float_value,
  48. /*v_min=*/ 0.0f,
  49. /*v_max=*/ 1.0f,
  50. /*speed=*/ 0,
  51. /*format=*/ "%.2f",
  52. /*variant=*/ knob_type,
  53. /*size=*/ knob_size,
  54. /*flags=*/ 0,
  55. /*steps=*/ 100
  56. );
  57. ImGui::SameLine();
  58. }
  59. ImGui::NewLine();
  60. ImGui::PopID();
  61. };
  62. auto show_int_knobs = [&knob_types](float knob_size)
  63. {
  64. std::string knob_size_str = std::to_string(knob_size);
  65. ImGui::PushID((knob_size_str + "_int").c_str());
  66. for (const auto& [knob_type, knob_typename] : knob_types)
  67. {
  68. ImGuiKnobs::KnobInt(
  69. knob_typename.c_str(),
  70. &knob_int_value,
  71. /*v_min=*/ 0.0,
  72. /*v_max=*/ 15,
  73. /*speed=*/ 0,
  74. /*format=*/ "%02i",
  75. /*variant=*/ knob_type,
  76. /*size=*/ knob_size,
  77. /*flags=*/ 0,
  78. /*steps=*/ 10
  79. );
  80. ImGui::SameLine();
  81. }
  82. ImGui::NewLine();
  83. ImGui::PopID();
  84. };
  85. // Apply custom colors before drawing knobs
  86. static bool useCustomColors = false;
  87. static ImVec4 primaryCol(0.1f, 0.45f, 0.7f, 1.f);
  88. static ImVec4 secondaryCol(0.7f, 0.7f, 0.7f, 1.f);
  89. static ImVec4 trackCol(0.3f, 0.3f, 0.7f, 1.f);
  90. if (useCustomColors)
  91. {
  92. ImGuiKnobs::KnobColors colors;
  93. colors.primary = ImGuiKnobs::color_set(ImColor(primaryCol));
  94. colors.secondary = ImGuiKnobs::color_set(ImColor(secondaryCol));
  95. colors.track = ImGuiKnobs::color_set(ImColor(trackCol));
  96. ImGuiKnobs::SetKnobColors(colors);
  97. }
  98. else
  99. {
  100. ImGuiKnobs::UnsetKnobColors();
  101. }
  102. float knobsSizeSmall = ImmApp::EmSize() * 2.5;
  103. float knobsSizeBig = knobsSizeSmall * 1.3;
  104. ImGui::BeginGroup();
  105. ImGui::Text("Some small knobs");
  106. show_float_knobs(knobsSizeSmall);
  107. ImGui::EndGroup();
  108. ImGui::SameLine();
  109. ImGui::BeginGroup();
  110. ImGui::Text("Some big knobs (int values)");
  111. show_int_knobs(knobsSizeBig);
  112. ImGui::EndGroup();
  113. // Customize colors button + popup (below the knobs)
  114. if (ImGui::Button("Customize Colors"))
  115. ImGui::OpenPopup("knob_colors_popup");
  116. if (ImGui::BeginPopup("knob_colors_popup"))
  117. {
  118. ImGui::Checkbox("Use custom colors", &useCustomColors);
  119. if (useCustomColors)
  120. {
  121. ImGui::ColorEdit4("Primary (indicator)", &primaryCol.x);
  122. ImGui::ColorEdit4("Secondary (circle)", &secondaryCol.x);
  123. ImGui::ColorEdit4("Track (arc)", &trackCol.x);
  124. }
  125. ImGui::EndPopup();
  126. }
  127. }
  128. void DemoSpinner()
  129. {
  130. ImGuiMd::RenderUnindented(R"(
  131. # Spinners
  132. [imspinner](https://github.com/dalerank/imspinner) provides spinners for ImGui.
  133. )");
  134. ImColor color(0.3f, 0.5f, 0.9f, 1.f);
  135. ImGui::Text("spinner_moving_dots");
  136. ImGui::SameLine();
  137. ImSpinner::SpinnerMovingDots("spinner_moving_dots", 20.0, 4.0, color, 20);
  138. ImGui::SameLine();
  139. float radius = ImGui::GetFontSize() / 1.8f;
  140. ImGui::Text("spinner_arc_rotation");
  141. ImGui::SameLine();
  142. ImSpinner::SpinnerArcRotation("spinner_arc_rotation", radius, 4.0, color);
  143. ImGui::SameLine();
  144. float radius1 = ImGui::GetFontSize() / 2.5f;
  145. ImGui::Text("spinner_ang_triple");
  146. ImGui::SameLine();
  147. ImSpinner::SpinnerAngTriple("spinner_ang_triple", radius1, radius1 * 1.5f, radius1 * 2.0f, 2.5f, color, color, color);
  148. static bool show_full_demo = false;
  149. ImGui::SameLine();
  150. ImGui::Checkbox("Show full spinners demo", &show_full_demo);
  151. if (show_full_demo)
  152. ImSpinner::demoSpinners();
  153. }
  154. void DemoToggle()
  155. {
  156. static bool flag = true;
  157. ImGuiMd::RenderUnindented(R"(
  158. # Toggle Switch
  159. [imgui_toggle](https://github.com/cmdwtf/imgui_toggle) provides toggle switches for ImGui."""
  160. )");
  161. bool changed = false;
  162. changed |= ImGui::Toggle("Default Toggle", &flag);
  163. ImGui::SameLine();
  164. changed |= ImGui::Toggle("Animated Toggle", &flag, ImGuiToggleFlags_Animated);
  165. ImGui::SameLine();
  166. auto toggle_config = ImGuiTogglePresets::MaterialStyle();
  167. toggle_config.AnimationDuration = 0.4f;
  168. changed |= ImGui::Toggle("Material Style (with slowed anim)", &flag, toggle_config);
  169. ImGui::SameLine();
  170. changed |= ImGui::Toggle("iOS style", &flag, ImGuiTogglePresets::iOSStyle(0.2f));
  171. ImGui::SameLine();
  172. changed |= ImGui::Toggle(
  173. "iOS style (light)", &flag, ImGuiTogglePresets::iOSStyle(0.2f, true));
  174. }
  175. void DemoPortableFileDialogs()
  176. {
  177. static std::string lastFileSelection;
  178. ImGui::PushID("pfd");
  179. ImGuiMd::RenderUnindented(R"(
  180. # Portable File Dialogs
  181. [portable-file-dialogs](https://github.com/samhocevar/portable-file-dialogs) provides file dialogs
  182. as well as notifications and messages. They will use the native dialogs and notifications on each platform.
  183. )");
  184. #ifdef __EMSCRIPTEN__
  185. ImGuiMd::RenderUnindented(R"(
  186. *Note: On Emscripten/Web, only messages dialogs (with an Ok button and an icon) are supported.
  187. On Windows, Linux and MacOS, everything is supported.*
  188. )");
  189. #endif
  190. ImGui::Text(" --- File dialogs ---");
  191. auto logResult = [](std::string what) {
  192. lastFileSelection = what;
  193. };
  194. auto logResultList = [](const std::vector<std::string>& whats) {
  195. lastFileSelection = fplus::join(std::string("\n"), whats);
  196. };
  197. static std::unique_ptr<pfd::open_file> openFileDialog;
  198. if (ImGui::Button("Open File"))
  199. openFileDialog = std::make_unique<pfd::open_file>("Select file");
  200. if (openFileDialog.get() && openFileDialog->ready())
  201. {
  202. logResultList(openFileDialog->result());
  203. openFileDialog.reset();
  204. }
  205. ImGui::SameLine();
  206. static std::unique_ptr<pfd::open_file> openFileMultiselect;
  207. if (ImGui::Button("Open File (multiselect)"))
  208. openFileMultiselect.reset(new pfd::open_file("Select file", "", {}, pfd::opt::multiselect));
  209. if (openFileMultiselect.get() && openFileMultiselect->ready())
  210. {
  211. logResultList(openFileMultiselect->result());
  212. openFileMultiselect.reset();
  213. }
  214. ImGui::SameLine();
  215. static std::unique_ptr<pfd::save_file> saveFileDialog;
  216. if (ImGui::Button("Save File"))
  217. saveFileDialog = std::make_unique<pfd::save_file>("Save file");
  218. if (saveFileDialog.get() && saveFileDialog->ready())
  219. {
  220. logResult(saveFileDialog->result());
  221. saveFileDialog.reset();
  222. }
  223. ImGui::SameLine();
  224. static std::unique_ptr<pfd::select_folder> selectFolderDialog;
  225. if (ImGui::Button("Select Folder"))
  226. selectFolderDialog = std::make_unique<pfd::select_folder>("Select folder");
  227. if (selectFolderDialog.get() && selectFolderDialog->ready())
  228. {
  229. logResult(selectFolderDialog->result());
  230. selectFolderDialog.reset();
  231. }
  232. if (lastFileSelection.size() > 0)
  233. ImGui::Text("%s", lastFileSelection.c_str());
  234. ImGui::Text(" --- Notifications and messages ---");
  235. static pfd::icon iconType = pfd::icon::info;
  236. static std::optional<pfd::message> messageDialog;
  237. static pfd::choice messageChoiceType = pfd::choice::ok;
  238. // icon type
  239. ImGui::Text("Icon type");
  240. ImGui::SameLine();
  241. std::vector<std::pair<pfd::icon, const char*>> iconTypes = {
  242. {pfd::icon::info, "info"},
  243. {pfd::icon::warning, "warning"},
  244. {pfd::icon::error, "error"},
  245. };
  246. for (const auto& [notification_icon, name]: iconTypes)
  247. {
  248. if (ImGui::RadioButton(name, iconType == notification_icon))
  249. iconType = notification_icon;
  250. ImGui::SameLine();
  251. }
  252. ImGui::NewLine();
  253. if (ImGui::Button("Add Notif"))
  254. pfd::notify("Notification title", "This is an example notification", iconType);
  255. // messages
  256. ImGui::SameLine();
  257. // 1. Display the message
  258. if (ImGui::Button("Add message"))
  259. messageDialog = pfd::message("Message title", "This is an example message", messageChoiceType, iconType);
  260. // 2. Handle the message result
  261. if (messageDialog.has_value() && messageDialog->ready())
  262. {
  263. printf("msg ready\n"); // Get the result via messageDialog->result()
  264. messageDialog.reset();
  265. }
  266. // Optional: Select the message type
  267. ImGui::SameLine();
  268. std::vector<std::pair<pfd::choice, const char*>> choiceTypes = {
  269. {pfd::choice::ok, "ok"},
  270. {pfd::choice::yes_no, "yes_no"},
  271. {pfd::choice::yes_no_cancel, "yes_no_cancel"},
  272. {pfd::choice::retry_cancel, "retry_cancel"},
  273. {pfd::choice::abort_retry_ignore, "abort_retry_ignore"},
  274. };
  275. for (const auto& [choice_type, name]: choiceTypes)
  276. {
  277. if (ImGui::RadioButton(name, messageChoiceType == choice_type))
  278. messageChoiceType = choice_type;
  279. ImGui::SameLine();
  280. }
  281. ImGui::NewLine();
  282. ImGui::PopID();
  283. }
  284. void DemoImFileDialog()
  285. {
  286. #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG
  287. static std::string selectedFilename;
  288. ImGuiMd::RenderUnindented(R"(
  289. # ImFileDialog
  290. [ImFileDialog](https://github.com/pthom/ImFileDialog.git) provides file dialogs for ImGui.
  291. )");
  292. ImGui::SameLine();
  293. ImGui::Text(ICON_FA_EXCLAMATION_TRIANGLE);
  294. ImGui::SetItemTooltip(
  295. "It is advised to use Portable File Dialogs instead, which offer native dialogs on each platform, "
  296. "as well as notifications and messages.\n\n"
  297. "Known limitations of ImFileDialog:\n"
  298. " * Not adapted for High DPI resolution under windows\n"
  299. " * No support for multi-selection\n"
  300. " * Will not work under python with a pure python backend (requires to use `immapp.run()`)"
  301. );
  302. if (ImGui::Button("Open file"))
  303. ifd::FileDialog::Instance().Open(
  304. "ShaderOpenDialog",
  305. "Open a shader",
  306. "Image file (*.png*.jpg*.jpeg*.bmp*.tga).png,.jpg,.jpeg,.bmp,.tga,.*",
  307. true
  308. );
  309. ImGui::SameLine();
  310. if (ImGui::Button("Open directory"))
  311. ifd::FileDialog::Instance().Open("DirectoryOpenDialog", "Open a directory", "");
  312. ImGui::SameLine();
  313. if (ImGui::Button("Save file"))
  314. ifd::FileDialog::Instance().Save("ShaderSaveDialog", "Save a shader", "*.sprj .sprj");
  315. if (selectedFilename.size() > 0)
  316. ImGui::Text("Last file selection:\n%s", selectedFilename.c_str());
  317. if (ifd::FileDialog::Instance().IsDone("ShaderOpenDialog"))
  318. {
  319. if (ifd::FileDialog::Instance().HasResult())
  320. {
  321. // get_results: plural form - ShaderOpenDialog supports multi-selection
  322. auto results = ifd::FileDialog::Instance().GetResults();
  323. selectedFilename = "";
  324. for (auto path: results)
  325. selectedFilename += path.string() + "\n";
  326. }
  327. ifd::FileDialog::Instance().Close();
  328. }
  329. if (ifd::FileDialog::Instance().IsDone("DirectoryOpenDialog"))
  330. {
  331. if (ifd::FileDialog::Instance().HasResult())
  332. selectedFilename = ifd::FileDialog::Instance().GetResult().string();
  333. ifd::FileDialog::Instance().Close();
  334. }
  335. if (ifd::FileDialog::Instance().IsDone("ShaderSaveDialog"))
  336. {
  337. if (ifd::FileDialog::Instance().HasResult())
  338. selectedFilename = ifd::FileDialog::Instance().GetResult().string();
  339. ifd::FileDialog::Instance().Close();
  340. }
  341. #endif // #ifdef IMGUI_BUNDLE_WITH_IMFILEDIALOG
  342. }
  343. void DemoCommandPalette()
  344. {
  345. static bool wasInited = false;
  346. static bool showCommandPalette = false;
  347. static ImCmd::Context * commandPaletteContext = nullptr;
  348. static int counter = 0;
  349. auto initCommandPalette = []()
  350. {
  351. commandPaletteContext = ImCmd::CreateContext();
  352. ImVec4 highlight_font_color(1.0f, 0.0f, 0.0f, 1.0f);
  353. ImCmd::SetStyleColor(ImCmdTextType_Highlight, ImGui::ColorConvertFloat4ToU32(highlight_font_color));
  354. // Add theme command: a two steps command, with initial callback + SubsequentCallback
  355. {
  356. ImCmd::Command select_theme_cmd;
  357. select_theme_cmd.Name = "Select theme";
  358. select_theme_cmd.InitialCallback = [&]() {
  359. ImCmd::Prompt(std::vector<std::string>{
  360. "Classic",
  361. "Dark",
  362. "Light",
  363. });
  364. };
  365. select_theme_cmd.SubsequentCallback = [&](int selected_option) {
  366. switch (selected_option) {
  367. case 0: ImGui::StyleColorsClassic(); break;
  368. case 1: ImGui::StyleColorsDark(); break;
  369. case 2: ImGui::StyleColorsLight(); break;
  370. default: break;
  371. }
  372. };
  373. ImCmd::AddCommand(std::move(select_theme_cmd));
  374. }
  375. // Simple command that increments a counter
  376. {
  377. ImCmd::Command inc_cmd;
  378. inc_cmd.Name = "increment counter";
  379. inc_cmd.InitialCallback = [] { counter += 1; };
  380. ImCmd::AddCommand(inc_cmd);
  381. }
  382. };
  383. if (!wasInited)
  384. {
  385. initCommandPalette();
  386. wasInited = true;
  387. }
  388. ImGuiMd::RenderUnindented(R"(
  389. # Command Palette
  390. [imgui-command-palette](https://github.com/hnOsmium0001/imgui-command-palette.git) provides a Sublime Text or VSCode style command palette in ImGui
  391. )");
  392. auto& io = ImGui::GetIO();
  393. if (io.KeyCtrl && io.KeyShift && ImGui::IsKeyPressed(ImGuiKey_P))
  394. showCommandPalette = ! showCommandPalette;
  395. if (showCommandPalette)
  396. ImCmd::CommandPaletteWindow("CommandPalette", &showCommandPalette);
  397. ImGui::NewLine();
  398. ImGui::Text("Press Ctrl+Shift+P to bring up the command palette");
  399. ImGui::NewLine();
  400. ImGui::Text("counter=%i", counter);
  401. }
  402. void DemoCoolBar()
  403. {
  404. auto ShowCoolBarButton = [](const std::string& label) -> bool
  405. {
  406. float w = ImGui::GetCoolBarItemWidth();
  407. // Display transparent image and check if clicked
  408. HelloImGui::ImageFromAsset("images/world.png", ImVec2(w, w));
  409. bool clicked = ImGui::IsItemHovered() && ImGui::IsMouseClicked(0);
  410. // Optional: add a label on the image
  411. {
  412. ImVec2 topLeftCorner = ImGui::GetItemRectMin();
  413. ImVec2 textPos(topLeftCorner.x + ImmApp::EmSize(1.f), topLeftCorner.y + ImmApp::EmSize(1.f));
  414. ImGui::GetForegroundDrawList()->AddText(textPos, 0xFFFFFFFF, label.c_str());
  415. }
  416. return clicked;
  417. };
  418. std::vector<std::string> buttonLabels {"A", "B", "C", "D", "E", "F"};
  419. ImGuiMd::RenderUnindented(R"(
  420. # ImCoolBar
  421. ImCoolBar provides a dock-like Cool bar for Dear ImGui
  422. )");
  423. ImGui::ImCoolBarSettings coolBarSettings;
  424. coolBarSettings.anchor = ImVec2(0.5f, 0.07f); // position in the window (ratio of window size)
  425. coolBarSettings.mode = ImCoolBarFlags_Horizontal;
  426. if (ImGui::BeginCoolBar("##CoolBarMain", coolBarSettings))
  427. {
  428. for (const std::string& label: buttonLabels)
  429. {
  430. if (ImGui::CoolBarItem())
  431. {
  432. if (ShowCoolBarButton(label))
  433. printf("Clicked %s\n", label.c_str());
  434. }
  435. }
  436. ImGui::EndCoolBar();
  437. }
  438. ImGui::NewLine(); ImGui::NewLine();
  439. }
  440. void demo_widgets()
  441. {
  442. DemoCoolBar();
  443. DemoToggle();
  444. DemoSpinner();
  445. DemoKnobs();
  446. DemoCommandPalette();
  447. ImGui::NewLine();
  448. DemoPortableFileDialogs();
  449. ImGui::NewLine();
  450. DemoImFileDialog();
  451. }