openMSX
ImGuiCpp.hh
Go to the documentation of this file.
1#ifndef IMGUI_CPP_HH
2#define IMGUI_CPP_HH
3
4#include "narrow.hh"
5#include "xrange.hh"
6
7#include <imgui.h>
8
9#include <concepts>
10
11// C++ wrapper around the Dear ImGui C-API
12//
13// Several Dear ImGui functions always need to be called in pairs. Some examples:
14// * ImGui::Begin() always needs to be paired with ImGui::End().
15// * Similar for ImGui::TreeNodeEx() and ImGui::TreePop().
16//
17// These wrapper ensure that you cannot do a wrong pairing.
18//
19// In case of the former 'End()' must always be called (whether 'Begin()'
20// returned 'true' or 'false'). But for the latter 'TreePop()' may only be
21// called when 'TreeNodeEx()' returned 'true'. This difference only exists for
22// historic reason (and thus for backwards compatibility). The Dear ImGui
23// documentation states that in some future version this difference will likely
24// be removed. These wrappers already hide this difference today.
25//
26// Example usage:
27// * This uses the original Dear ImGui C-API:
28// if (ImGui::Begin("my-window")) {
29// ImGui::BeginDisabled(b);
30// if (ImGui::TreeNodeEx("bla", flag)) {
31// ... more stuff
32// ImGui::TreePop();
33// }
34// if (ImGui::TreeNodeEx("foobar")) {
35// ... more stuff
36// ImGui::TreePop();
37// }
38// ImGui::EndDisabled();
39// }
40// ImGui::End();
41//
42// * This is the exact same example, but with our C++ wrapper functions:
43// im::Window("my-window", [&]{
44// im::Disabled(b, [&]{
45// im::TreeNode("bla", flag, [&]{
46// ... more stuff
47// });
48// im::TreeNode("foobar", [&]{
49// ... more stuff
50// });
51// });
52// });
53//
54// This wrapper is inspired by ideas from:
55// https://github.com/ocornut/imgui/issues/2096
56// https://github.com/ocornut/imgui/pull/2197
57// https://github.com/mnesarco/imgui_sugar
58// https://github.com/kfsone/imguiwrap
59
60namespace im {
61
62// im::Window(): wrapper around ImGui::Begin() / ImGui::End()
63inline void Window(const char* name, bool* p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
64{
65 if (ImGui::Begin(name, p_open, flags)) {
66 next();
67 }
68 ImGui::End();
69}
70inline void Window(const char* name, bool* p_open, std::invocable<> auto next)
71{
72 Window(name, p_open, 0, next);
73}
74inline void Window(const char* name, std::invocable<> auto next)
75{
76 Window(name, nullptr, 0, next);
77}
78
80 bool open = false; // [level] true <=> window is open
81 bool do_raise = false; // [edge] set to true when you want to raise this window
82 // gets automatically reset when done
83 void raise() { do_raise = open = true; }
84};
85inline void Window(const char* name, WindowStatus& status, ImGuiWindowFlags flags, std::invocable<> auto next)
86{
87 if (ImGui::Begin(name, &status.open, flags)) {
88 if (status.do_raise) {
89 status.do_raise = false;
90 if (!ImGui::IsWindowAppearing()) { // otherwise crash, viewport not yet initialized???
91 // depending on the backend (e.g. Wayland) this could be nullptr
92 if (auto* swf = ImGui::GetPlatformIO().Platform_SetWindowFocus) {
93 swf(ImGui::GetWindowViewport());
94 }
95 // When window is inside the main viewport, this function is
96 // needed to raise focus even if Platform_SetWindowFocus exists
97 ImGui::SetWindowFocus();
98 }
99 }
100 next();
101 }
102 ImGui::End();
103}
104inline void Window(const char* name, WindowStatus& status, std::invocable<> auto next)
105{
106 Window(name, status, 0, next);
107}
108
109// im::Child(): wrapper around ImGui::BeginChild() / ImGui::EndChild()
110inline void Child(const char* str_id, const ImVec2& size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags, std::invocable<> auto next)
111{
112 if (ImGui::BeginChild(str_id, size, child_flags, window_flags)) {
113 next();
114 }
115 ImGui::EndChild();
116}
117inline void Child(const char* str_id, const ImVec2& size, ImGuiChildFlags child_flags, std::invocable<> auto next)
118{
119 Child(str_id, size, child_flags, 0, next);
120}
121inline void Child(const char* str_id, const ImVec2& size, std::invocable<> auto next)
122{
123 Child(str_id, size, 0, 0, next);
124}
125inline void Child(const char* str_id, std::invocable<> auto next)
126{
127 Child(str_id, {}, 0, 0, next);
128}
129
130// im::Font(): wrapper around ImGui::PushFont() / ImGui::PopFont()
131inline void Font(ImFont* font, std::invocable<> auto next)
132{
133 ImGui::PushFont(font);
134 next();
135 ImGui::PopFont();
136}
137// Same functionality as im::Font(), but different usage (sometimes one sometimes the other is easier).
139 explicit ScopedFont(ImFont* font) { ImGui::PushFont(font); }
140 ~ScopedFont() { ImGui::PopFont(); }
141
142 ScopedFont(const ScopedFont&) = delete;
144 ScopedFont& operator=(const ScopedFont&) = delete;
146};
147
148// im::StyleColor(): wrapper around ImGui::PushStyleColor() / ImGui::PopStyleColor()
149// Can be called like:
150// im::StyleColor(
151// bool active, // _optional_ boolean parameter
152// ImGuiCol idx1, ImVec4 col1, // followed by an arbitrary number of [idx, col] pairs
153// ImGuiCol idx2, ImU32 col2, // where col can either be 'ImVec4' or 'ImU32'
154// ...
155// std::invocable<> auto next); // and finally a lambda that will be executed with these color changes
156template<int N>
157inline void StyleColor_impl(bool active, std::invocable<> auto next)
158{
159 next();
160 if (active) ImGui::PopStyleColor(N);
161}
162template<int N, typename... Args>
163inline void StyleColor_impl(bool active, ImGuiCol idx, ImVec4 col, Args&& ...args)
164{
165 if (active) ImGui::PushStyleColor(idx, col);
166 StyleColor_impl<N>(active, std::forward<Args>(args)...);
167}
168template<int N, typename... Args>
169inline void StyleColor_impl(bool active, ImGuiCol idx, ImU32 col, Args&& ...args)
170{
171 if (active) ImGui::PushStyleColor(idx, ImGui::ColorConvertU32ToFloat4(col));
172 StyleColor_impl<N>(active, std::forward<Args>(args)...);
173}
174template<typename... Args>
175inline void StyleColor(bool active, Args&& ...args)
176{
177 static constexpr auto N = sizeof...(args);
178 static_assert(N >= 3);
179 static_assert((N & 1) == 1);
180 StyleColor_impl<(N - 1) / 2>(active, std::forward<Args>(args)...);
181}
182template<typename... Args>
183inline void StyleColor(Args&& ...args)
184{
185 StyleColor(true, std::forward<Args>(args)...);
186}
187
188// im::StyleVar(): wrapper around ImGui::PushStyleVar() / ImGui::PopStyleVar()
189// Add more overloads when needed
190inline void StyleVar(ImGuiStyleVar idx, float val, std::invocable<> auto next)
191{
192 ImGui::PushStyleVar(idx, val);
193 next();
194 ImGui::PopStyleVar(1);
195}
196inline void StyleVar(ImGuiStyleVar idx, const ImVec2& val, std::invocable<> auto next)
197{
198 ImGui::PushStyleVar(idx, val);
199 next();
200 ImGui::PopStyleVar(1);
201}
202
203// im::ItemWidth(): wrapper around ImGui::PushItemWidth() / ImGui::PopItemWidth()
204inline void ItemWidth(float item_width, std::invocable<> auto next)
205{
206 ImGui::PushItemWidth(item_width);
207 next();
208 ImGui::PopItemWidth();
209}
210
211// im::TextWrapPos(): wrapper around ImGui::PushTextWrapPos() / ImGui::PopTextWrapPos()
212inline void TextWrapPos(float wrap_local_pos_x, std::invocable<> auto next)
213{
214 ImGui::PushTextWrapPos(wrap_local_pos_x);
215 next();
216 ImGui::PopTextWrapPos();
217}
218inline void TextWrapPos(std::invocable<> auto next)
219{
220 TextWrapPos(0.0f, next);
221}
222
223// im::Indent(): wrapper around ImGui::Indent() / ImGui::Unindent()
224inline void Indent(float indent_w, std::invocable<> auto next)
225{
226 ImGui::Indent(indent_w);
227 next();
228 ImGui::Unindent(indent_w);
229}
230inline void Indent(std::invocable<> auto next)
231{
232 Indent(0.0f, next);
233}
234
235// im::Group(): wrapper around ImGui::BeginGroup() / ImGui::EndGroup()
236inline void Group(std::invocable<> auto next)
237{
238 ImGui::BeginGroup();
239 next();
240 ImGui::EndGroup();
241}
242
243// im::ID(): wrapper around ImGui::PushID() / ImGui::PopID()
244inline void ID(const char* str_id, std::invocable<> auto next)
245{
246 ImGui::PushID(str_id);
247 next();
248 ImGui::PopID();
249}
250inline void ID(const char* str_id_begin, const char* str_id_end, std::invocable<> auto next)
251{
252 ImGui::PushID(str_id_begin, str_id_end);
253 next();
254 ImGui::PopID();
255}
256inline void ID(const void* ptr_id, std::invocable<> auto next)
257{
258 ImGui::PushID(ptr_id);
259 next();
260 ImGui::PopID();
261}
262inline void ID(int int_id, std::invocable<> auto next)
263{
264 ImGui::PushID(int_id);
265 next();
266 ImGui::PopID();
267}
268inline void ID(const std::string& str, std::invocable<> auto next)
269{
270 auto begin = str.data();
271 auto end = begin + str.size();
272 ID(begin, end, next);
273}
274inline void ID(std::string_view str, std::invocable<> auto next)
275{
276 auto begin = str.data();
277 auto end = begin + str.size();
278 ID(begin, end, next);
279}
280
281inline void ID_for_range(int count, std::invocable<int> auto next)
282{
283 for (auto i : xrange(count)) {
284 ID(i, [&]{ next(i); });
285 }
286}
287inline void ID_for_range(size_t count, std::invocable<int> auto next)
288{
289 ID_for_range(narrow<int>(count), next);
290}
291
292// im::Combo(): wrapper around ImGui::BeginCombo() / ImGui::EndCombo()
293inline void Combo(const char* label, const char* preview_value, ImGuiComboFlags flags, std::invocable<> auto next)
294{
295 if (ImGui::BeginCombo(label, preview_value, flags)) {
296 next();
297 ImGui::EndCombo();
298 }
299}
300inline void Combo(const char* label, const char* preview_value, std::invocable<> auto next)
301{
302 Combo(label, preview_value, 0, next);
303}
304
305// im::TreeNode(): wrapper around ImGui::TreeNodeEx() / ImGui::TreePop()
306inline bool TreeNode(const char* label, ImGuiTreeNodeFlags flags, std::invocable<> auto next)
307{
308 bool open = ImGui::TreeNodeEx(label, flags);
309 if (open) {
310 next();
311 ImGui::TreePop();
312 }
313 return open;
314}
315inline bool TreeNode(const char* label, std::invocable<> auto next)
316{
317 return TreeNode(label, 0, next);
318}
319inline void TreeNode(const char* label, bool* p_open, std::invocable<> auto next)
320{
321 assert(p_open);
322 ImGui::SetNextItemOpen(*p_open);
323 int flags = 0;
324 *p_open = ImGui::TreeNodeEx(label, flags);
325 if (*p_open) {
326 next();
327 ImGui::TreePop();
328 }
329}
330
331// im::ListBox(): wrapper around ImGui::BeginListBox() / ImGui::EndListBox()
332inline void ListBox(const char* label, const ImVec2& size, std::invocable<> auto next)
333{
334 if (ImGui::BeginListBox(label, size)) {
335 next();
336 ImGui::EndListBox();
337 }
338}
339inline void ListBox(const char* label, std::invocable<> auto next)
340{
341 ListBox(label, {}, next);
342}
343
344// im::MainMenuBar(): wrapper around ImGui::BeginMenuBar() / ImGui::EndMenuBar()
345inline void MenuBar(std::invocable<> auto next)
346{
347 if (ImGui::BeginMenuBar()) {
348 next();
349 ImGui::EndMenuBar();
350 }
351}
352
353// im::MainMenuBar(): wrapper around ImGui::BeginMainMenuBar() / ImGui::EndMainMenuBar()
354inline void MainMenuBar(std::invocable<> auto next)
355{
356 if (ImGui::BeginMainMenuBar()) {
357 next();
358 ImGui::EndMainMenuBar();
359 }
360}
361
362// im::Menu(): wrapper around ImGui::BeginMenu() / ImGui::EndMenu()
363inline bool Menu(const char* label, bool enabled, std::invocable<> auto next)
364{
365 bool open = ImGui::BeginMenu(label, enabled);
366 if (open) {
367 next();
368 ImGui::EndMenu();
369 }
370 return open;
371}
372inline bool Menu(const char* label, std::invocable<> auto next)
373{
374 return Menu(label, true, next);
375}
376
377// im::Tooltip(): wrapper around ImGui::BeginTooltip() / ImGui::EndTooltip()
378inline void Tooltip(std::invocable<> auto next)
379{
380 if (ImGui::BeginTooltip()) {
381 next();
382 ImGui::EndTooltip();
383 }
384}
385// im::Tooltip(): wrapper around ImGui::BeginItemTooltip() / ImGui::EndTooltip()
386inline void ItemTooltip(std::invocable<> auto next)
387{
388 if (ImGui::BeginItemTooltip()) {
389 next();
390 ImGui::EndTooltip();
391 }
392}
393
394// im::Popup(): wrapper around ImGui::BeginPopup() / ImGui::EndPopup()
395inline void Popup(const char* str_id, ImGuiWindowFlags flags, std::invocable<> auto next)
396{
397 if (ImGui::BeginPopup(str_id, flags)) {
398 next();
399 ImGui::EndPopup();
400 }
401}
402inline void Popup(const char* str_id, std::invocable<> auto next)
403{
404 Popup(str_id, 0, next);
405}
406
407// im::PopupModal(): wrapper around ImGui::BeginPopupModal() / ImGui::EndPopup()
408inline void PopupModal(const char* name, bool* p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
409{
410 if (ImGui::BeginPopupModal(name, p_open, flags)) {
411 next();
412 ImGui::EndPopup();
413 }
414}
415inline void PopupModal(const char* name, bool* p_open, std::invocable<> auto next)
416{
417 PopupModal(name, p_open, 0, next);
418}
419inline void PopupModal(const char* name, std::invocable<> auto next)
420{
421 PopupModal(name, nullptr, 0, next);
422}
423
424// im::PopupContextItem(): wrapper around ImGui::BeginPopupContextItem() / ImGui::EndPopup()
425inline void PopupContextItem(const char* str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
426{
427 if (ImGui::BeginPopupContextItem(str_id, popup_flags)) {
428 next();
429 ImGui::EndPopup();
430 }
431}
432inline void PopupContextItem(const char* str_id, std::invocable<> auto next)
433{
434 PopupContextItem(str_id, ImGuiPopupFlags_MouseButtonRight, next);
435}
436inline void PopupContextItem(std::invocable<> auto next)
437{
438 PopupContextItem(nullptr, ImGuiPopupFlags_MouseButtonRight, next);
439}
440
441// im::PopupContextWindow(): wrapper around ImGui::BeginPopupContextWindow() / ImGui::EndPopup()
442inline void PopupContextWindow(const char* str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
443{
444 if (ImGui::BeginPopupContextWindow(str_id, popup_flags)) {
445 next();
446 ImGui::EndPopup();
447 }
448}
449inline void PopupContextWindow(const char* str_id, std::invocable<> auto next)
450{
451 PopupContextWindow(str_id, 1, next);
452}
453inline void PopupContextWindow(std::invocable<> auto next)
454{
455 PopupContextWindow(nullptr, 1, next);
456}
457
458// im::Table(): wrapper around ImGui::BeginTable() / ImGui::EndTable()
459inline void Table(const char* str_id, int column, ImGuiTableFlags flags, const ImVec2& outer_size, float inner_width, std::invocable<> auto next)
460{
461 if (ImGui::BeginTable(str_id, column, flags, outer_size, inner_width)) {
462 next();
463 ImGui::EndTable();
464 }
465}
466inline void Table(const char* str_id, int column, ImGuiTableFlags flags, const ImVec2& outer_size, std::invocable<> auto next)
467{
468 Table(str_id, column, flags, outer_size, 0.0f, next);
469}
470inline void Table(const char* str_id, int column, ImGuiTableFlags flags, std::invocable<> auto next)
471{
472 Table(str_id, column, flags, {}, 0.0f, next);
473}
474inline void Table(const char* str_id, int column, std::invocable<> auto next)
475{
476 Table(str_id, column, 0, {}, 0.0f, next);
477}
478
479// im::TabBar(): wrapper around ImGui::BeginTabBar() / ImGui::EndTabBar()
480inline void TabBar(const char* str_id, ImGuiTabBarFlags flags, std::invocable<> auto next)
481{
482 if (ImGui::BeginTabBar(str_id, flags)) {
483 next();
484 ImGui::EndTabBar();
485 }
486}
487inline void TabBar(const char* str_id, std::invocable<> auto next)
488{
489 TabBar(str_id, 0, next);
490}
491
492// im::TabItem(): wrapper around ImGui::BeginTabItem() / ImGui::EndTabItem()
493inline void TabItem(const char* label, bool* p_open, ImGuiTabItemFlags flags, std::invocable<> auto next)
494{
495 if (ImGui::BeginTabItem(label, p_open, flags)) {
496 next();
497 ImGui::EndTabItem();
498 }
499}
500inline void TabItem(const char* label, bool* p_open, std::invocable<> auto next)
501{
502 TabItem(label, p_open, 0, next);
503}
504inline void TabItem(const char* label, std::invocable<> auto next)
505{
506 TabItem(label, nullptr, 0, next);
507}
508
509// im::Disabled(): wrapper around ImGui::BeginDisabled() / ImGui::EndDisabled()
510inline void Disabled(bool b, std::invocable<> auto next)
511{
512 ImGui::BeginDisabled(b);
513 next();
514 ImGui::EndDisabled();
515}
516
517// im::DisabledIndent(): combination of Disabled() and Indent()
518inline void DisabledIndent(bool b, std::invocable<> auto next)
519{
520 ImGui::BeginDisabled(b);
521 ImGui::Indent(); // TODO for now not configurable
522 next();
523 ImGui::Unindent();
524 ImGui::EndDisabled();
525}
526
527// im::VisuallyDisabled(): similar to Disabled(), but only visually disable, still allow to interact normally
528inline void VisuallyDisabled(bool b, std::invocable<> auto next)
529{
530 if (b) {
531 const auto& style = ImGui::GetStyle();
532 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, style.Alpha * style.DisabledAlpha);
533 }
534 next();
535 if (b) {
536 ImGui::PopStyleVar(1);
537 }
538}
539
540// im::ListClipper: wrapper around ImGuiListClipper
541// hides the typical nested loop
542inline void ListClipper(size_t count, int forceIndex, float lineHeight, std::invocable<int> auto next)
543{
544 ImGuiListClipper clipper; // only draw the actually visible lines
545 clipper.Begin(narrow<int>(count), lineHeight);
546 if (forceIndex > 0) clipper.IncludeItemByIndex(narrow<int>(forceIndex));
547 while (clipper.Step()) {
548 for (int i : xrange(clipper.DisplayStart, clipper.DisplayEnd)) {
549 next(i);
550 }
551 }
552}
553inline void ListClipper(size_t count, int forceIndex, std::invocable<int> auto next)
554{
555 ListClipper(count, forceIndex, -1.0f, next);
556}
557inline void ListClipper(size_t count, std::invocable<int> auto next)
558{
559 ListClipper(count, -1, next);
560}
561
562// im::ListClipperID: combination of im::ListClipper() and im::ID()
563inline void ListClipperID(size_t count, std::invocable<int> auto next)
564{
565 ImGuiListClipper clipper; // only draw the actually visible lines
566 clipper.Begin(narrow<int>(count));
567 while (clipper.Step()) {
568 for (int i : xrange(clipper.DisplayStart, clipper.DisplayEnd)) {
569 ImGui::PushID(i);
570 next(i);
571 ImGui::PopID();
572 }
573 }
574}
575
576} // namespace im
577
578#endif
Definition ImGuiCpp.hh:60
void DisabledIndent(bool b, std::invocable<> auto next)
Definition ImGuiCpp.hh:518
void Table(const char *str_id, int column, ImGuiTableFlags flags, const ImVec2 &outer_size, float inner_width, std::invocable<> auto next)
Definition ImGuiCpp.hh:459
void MainMenuBar(std::invocable<> auto next)
Definition ImGuiCpp.hh:354
void MenuBar(std::invocable<> auto next)
Definition ImGuiCpp.hh:345
void Window(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:63
void VisuallyDisabled(bool b, std::invocable<> auto next)
Definition ImGuiCpp.hh:528
void ID(const char *str_id, std::invocable<> auto next)
Definition ImGuiCpp.hh:244
void PopupContextItem(const char *str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:425
void StyleColor_impl(bool active, std::invocable<> auto next)
Definition ImGuiCpp.hh:157
void StyleVar(ImGuiStyleVar idx, float val, std::invocable<> auto next)
Definition ImGuiCpp.hh:190
void TabBar(const char *str_id, ImGuiTabBarFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:480
void PopupContextWindow(const char *str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:442
bool TreeNode(const char *label, ImGuiTreeNodeFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:306
void Combo(const char *label, const char *preview_value, ImGuiComboFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:293
void ItemWidth(float item_width, std::invocable<> auto next)
Definition ImGuiCpp.hh:204
void ListBox(const char *label, const ImVec2 &size, std::invocable<> auto next)
Definition ImGuiCpp.hh:332
void StyleColor(bool active, Args &&...args)
Definition ImGuiCpp.hh:175
void Child(const char *str_id, const ImVec2 &size, ImGuiChildFlags child_flags, ImGuiWindowFlags window_flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:110
void PopupModal(const char *name, bool *p_open, ImGuiWindowFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:408
void TextWrapPos(float wrap_local_pos_x, std::invocable<> auto next)
Definition ImGuiCpp.hh:212
bool Menu(const char *label, bool enabled, std::invocable<> auto next)
Definition ImGuiCpp.hh:363
void Disabled(bool b, std::invocable<> auto next)
Definition ImGuiCpp.hh:510
void Group(std::invocable<> auto next)
Definition ImGuiCpp.hh:236
void Font(ImFont *font, std::invocable<> auto next)
Definition ImGuiCpp.hh:131
void TabItem(const char *label, bool *p_open, ImGuiTabItemFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:493
void Tooltip(std::invocable<> auto next)
Definition ImGuiCpp.hh:378
void Indent(float indent_w, std::invocable<> auto next)
Definition ImGuiCpp.hh:224
void ListClipper(size_t count, int forceIndex, float lineHeight, std::invocable< int > auto next)
Definition ImGuiCpp.hh:542
void ListClipperID(size_t count, std::invocable< int > auto next)
Definition ImGuiCpp.hh:563
void Popup(const char *str_id, ImGuiWindowFlags flags, std::invocable<> auto next)
Definition ImGuiCpp.hh:395
void ItemTooltip(std::invocable<> auto next)
Definition ImGuiCpp.hh:386
void ID_for_range(int count, std::invocable< int > auto next)
Definition ImGuiCpp.hh:281
ScopedFont(ImFont *font)
Definition ImGuiCpp.hh:139
ScopedFont(const ScopedFont &)=delete
ScopedFont(ScopedFont &&)=delete
ScopedFont & operator=(ScopedFont &&)=delete
ScopedFont & operator=(const ScopedFont &)=delete
constexpr auto xrange(T e)
Definition xrange.hh:132
constexpr auto begin(const zstring_view &x)
constexpr auto end(const zstring_view &x)