openMSX
ImGuiPartInterface.hh
Go to the documentation of this file.
1#ifndef IMGUI_PARTINTERFACE_HH
2#define IMGUI_PARTINTERFACE_HH
3
4#include "ImGuiCpp.hh"
5
6#include "StringOp.hh"
7#include "escape_newline.hh"
8#include "stl.hh"
9#include "zstring_view.hh"
10
11#include <initializer_list>
12#include <string>
13#include <string_view>
14
15#include <imgui.h>
16
17namespace openmsx {
18
19class MSXMotherBoard;
20
22{
23public:
24 [[nodiscard]] virtual zstring_view iniName() const { return ""; }
25 virtual void save(ImGuiTextBuffer& /*buf*/) {}
26 virtual void loadStart() {}
27 virtual void loadLine(std::string_view /*name*/, zstring_view /*value*/) {}
28 virtual void loadEnd() {}
29
30 virtual void showMenu(MSXMotherBoard* /*motherBoard*/) {}
31 virtual void paint(MSXMotherBoard* /*motherBoard*/) {}
32};
33
35
36template<typename C, typename T> struct PersistentElementBase {
37 constexpr PersistentElementBase(zstring_view name_, T C::*p_)
38 : name(name_), p(p_) {}
39
41 T C::*p;
42
43 T& get(C& c) const { return c.*p; }
44};
45
46// 'PersistentElement' base-case, will be partially specialized for concrete 'T'.
47template<typename C, typename T>
49template<typename C, typename T>
51
52template<typename C>
54 using PersistentElementBase<C, int>::PersistentElementBase;
55 void save(ImGuiTextBuffer& buf, C& c) const {
56 buf.appendf("%s=%d\n", this->name.c_str(), this->get(c));
57 }
58 void load(C& c, zstring_view value) const {
59 if (auto r = StringOp::stringTo<int>(value)) {
60 this->get(c) = *r;
61 }
62 }
63};
64
65template<typename C>
67 int max;
68 constexpr PersistentElementMax(zstring_view name_, int C::*p_, int max_)
69 : PersistentElement<C, int>(name_, p_), max(max_) {}
70
71 void load(C& c, std::string_view value) const {
72 if (auto r = StringOp::stringTo<int>(value)) {
73 if (0 <= *r && *r < max) this->get(c) = *r;
74 }
75 }
76};
77
78template<typename C>
80 int min, max;
81 constexpr PersistentElementMinMax(zstring_view name_, int C::*p_, int min_, int max_)
82 : PersistentElement<C, int>(name_, p_), min(min_), max(max_) {}
83
84 void load(C& c, std::string_view value) const {
85 if (auto r = StringOp::stringTo<int>(value)) {
86 if (min <= *r && *r < max) this->get(c) = *r;
87 }
88 }
89};
90
91template<typename C>
93 std::initializer_list<int> valid;
94 constexpr PersistentElementEnum(zstring_view name_, int C::*p_, std::initializer_list<int> valid_)
95 : PersistentElement<C, int>(name_, p_), valid(valid_) {}
96
97 void load(C& c, std::string_view value) const {
98 if (auto r = StringOp::stringTo<int>(value)) {
99 if (contains(valid, *r)) this->get(c) = *r;
100 }
101 }
102};
103
104template<typename C>
105struct PersistentElement<C, unsigned> : PersistentElementBase<C, unsigned> {
106 using PersistentElementBase<C, unsigned>::PersistentElementBase;
107 void save(ImGuiTextBuffer& buf, C& c) const {
108 buf.appendf("%s=%u\n", this->name.c_str(), this->get(c));
109 }
110 void load(C& c, zstring_view value) const {
111 if (auto r = StringOp::stringTo<unsigned>(value)) {
112 this->get(c) = *r;
113 }
114 }
115};
116
117template<typename C>
118struct PersistentElement<C, bool> : PersistentElementBase<C, bool> {
119 using PersistentElementBase<C, bool>::PersistentElementBase;
120 void save(ImGuiTextBuffer& buf, C& c) const {
121 buf.appendf("%s=%d\n", this->name.c_str(), this->get(c));
122 }
123 void load(C& c, zstring_view value) const {
124 this->get(c) = StringOp::stringToBool(value);
125 }
126};
127
128template<typename C>
129struct PersistentElement<C, float> : PersistentElementBase<C, float> {
130 using PersistentElementBase<C, float>::PersistentElementBase;
131 void save(ImGuiTextBuffer& buf, C& c) const {
132 buf.appendf("%s=%f\n", this->name.c_str(), double(this->get(c))); // cast to silence warning
133 }
134 void load(C& c, zstring_view value) const {
135 this->get(c) = strtof(value.c_str(), nullptr); // TODO error handling
136 }
137};
138
139template<typename C>
140struct PersistentElement<C, std::string> : PersistentElementBase<C, std::string> {
141 using PersistentElementBase<C, std::string>::PersistentElementBase;
142 void save(ImGuiTextBuffer& buf, C& c) const {
143 buf.appendf("%s=%s\n", this->name.c_str(), escape_newline::encode(this->get(c)).c_str());
144 }
145 void load(C& c, zstring_view value) const {
146 this->get(c) = escape_newline::decode(value);
147 }
148};
149
150template<typename C>
151struct PersistentElement<C, gl::ivec2> : PersistentElementBase<C, gl::ivec2> {
152 using PersistentElementBase<C, gl::ivec2>::PersistentElementBase;
153 void save(ImGuiTextBuffer& buf, C& c) const {
154 const auto& v = this->get(c);
155 buf.appendf("%s=[ %d %d ]\n", this->name.c_str(), v.x, v.y);
156 }
157 void load(C& c, zstring_view value) const {
158 gl::ivec2 t;
159 if (sscanf(value.c_str(), "[ %d %d ]", &t.x, &t.y) == 2) {
160 this->get(c) = t;
161 }
162 }
163};
164
165template<typename C>
166struct PersistentElement<C, gl::vec2> : PersistentElementBase<C, gl::vec2> {
167 using PersistentElementBase<C, gl::vec2>::PersistentElementBase;
168 void save(ImGuiTextBuffer& buf, C& c) const {
169 const auto& v = this->get(c);
170 buf.appendf("%s=[ %f %f ]\n", this->name.c_str(),
171 double(v.x), double(v.y)); // note: cast only needed to silence warnings
172 }
173 void load(C& c, zstring_view value) const {
174 gl::vec2 t;
175 if (sscanf(value.c_str(), "[ %f %f ]", &t.x, &t.y) == 2) {
176 this->get(c) = t;
177 }
178 }
179};
180
181template<typename C>
182struct PersistentElement<C, gl::vec4> : PersistentElementBase<C, gl::vec4> {
183 using PersistentElementBase<C, gl::vec4>::PersistentElementBase;
184 void save(ImGuiTextBuffer& buf, C& c) const {
185 const auto& v = this->get(c);
186 buf.appendf("%s=[ %f %f %f %f ]\n", this->name.c_str(),
187 double(v.x), double(v.y), double(v.z), double(v.w)); // note: cast only needed to silence warnings
188 }
189 void load(C& c, zstring_view value) const {
190 gl::vec4 t;
191 if (sscanf(value.c_str(), "[ %f %f %f %f ]", &t.x, &t.y, &t.z, &t.w) == 4) {
192 this->get(c) = t;
193 }
194 }
195};
196
197template<typename C>
198struct PersistentElement<C, im::WindowStatus> : PersistentElementBase<C, im::WindowStatus> {
199 using PersistentElementBase<C, im::WindowStatus>::PersistentElementBase;
200 void save(ImGuiTextBuffer& buf, C& c) const {
201 buf.appendf("%s=%d\n", this->name.c_str(), this->get(c).open);
202 }
203 void load(C& c, zstring_view value) const {
204 this->get(c).open = StringOp::stringToBool(value);
205 }
206};
207
208
209template<typename C, typename... Elements>
210void savePersistent(ImGuiTextBuffer& buf, C& c, const std::tuple<Elements...>& tup)
211{
212 std::apply([&](auto& ...elem){(..., elem.save(buf, c));}, tup);
213}
214
215template<typename C, typename Elem>
216bool checkLoad(std::string_view name, zstring_view value,
217 C& c, Elem& elem)
218{
219 if (name != elem.name) return false;
220 elem.load(c, value);
221 return true;
222}
223template<typename C, typename... Elements>
224bool loadOnePersistent(std::string_view name, zstring_view value,
225 C& c, const std::tuple<Elements...>& tup)
226{
227 return std::apply([&](auto& ...elem){ return (... || checkLoad(name, value, c, elem));}, tup);
228}
229
230} // namespace openmsx
231
232#endif
TclObject t
virtual zstring_view iniName() const
virtual void showMenu(MSXMotherBoard *)
virtual void loadLine(std::string_view, zstring_view)
virtual void paint(MSXMotherBoard *)
virtual void save(ImGuiTextBuffer &)
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
constexpr const char * c_str() const
bool stringToBool(string_view str)
Definition StringOp.cc:16
std::string decode(std::string_view input)
std::string encode(std::string_view input)
Definition gl_mat.hh:23
Definition ImGuiCpp.hh:60
This file implemented 3 utility functions:
Definition Autofire.cc:11
bool loadOnePersistent(std::string_view name, zstring_view value, C &c, const std::tuple< Elements... > &tup)
void savePersistent(ImGuiTextBuffer &buf, C &c, const std::tuple< Elements... > &tup)
bool checkLoad(std::string_view name, zstring_view value, C &c, Elem &elem)
STL namespace.
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
Definition stl.hh:32
constexpr PersistentElementBase(zstring_view name_, T C::*p_)
void load(C &c, std::string_view value) const
constexpr PersistentElementEnum(zstring_view name_, int C::*p_, std::initializer_list< int > valid_)
std::initializer_list< int > valid
void load(C &c, std::string_view value) const
constexpr PersistentElementMax(zstring_view name_, int C::*p_, int max_)
void load(C &c, std::string_view value) const
constexpr PersistentElementMinMax(zstring_view name_, int C::*p_, int min_, int max_)
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const
void load(C &c, zstring_view value) const
void save(ImGuiTextBuffer &buf, C &c) const