16#include <imgui_stdlib.h>
26 ImGui::TextDisabled(
"(?)");
32 auto pos = ImGui::GetCursorScreenPos();
33 auto color = ImGui::GetColorU32(ImGuiCol_ButtonHovered);
40 if (ImGui::IsItemHovered()) {
42 auto* drawList = ImGui::GetWindowDrawList();
43 ImVec2 p1{pos.x, pos.y + size.y};
44 ImVec2 p2{pos.x + size.x, pos.y + size.y};
45 drawList->AddLine(p1, p2, color);
48 if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) {
49 SDL_OpenURL(url.
c_str());
55 return std::string(
setting.getDescription());
58template<std::invocable<const Setting&> GetTooltip = GetSettingDescription>
59static void settingStuff(
Setting&
setting, GetTooltip getTooltip = {})
64 auto defaultString = defaultValue.
getString();
66 if (defaultString.empty()) {
68 ImGui::TextDisabled(
"<empty>");
70 if (ImGui::Button(
"Restore default")) {
73 }
catch (MSXException&) {
76 ImGui::CloseCurrentPopup();
88 bool value =
setting.getBoolean();
89 bool changed = ImGui::Checkbox(label, &value);
91 if (changed)
setting.setBoolean(value);
95 settingStuff(
setting, getTooltip);
99 auto spacing = std::max(0.0f, ImGui::GetContentRegionAvail().x -
ImGui::CalcTextSize(shortCut).x);
100 ImGui::SameLine(0.0f, spacing);
101 ImGui::TextDisabled(
"%s", shortCut.c_str());
114 int min =
setting.getMinValue();
115 int max =
setting.getMaxValue();
116 bool changed = ImGui::SliderInt(label, &value, min, max,
"%d", flags);
118 if (changed)
setting.setInt(value);
133 float value =
setting.getFloat();
134 float min = narrow_cast<float>(
setting.getMinValue());
135 float max = narrow_cast<float>(
setting.getMaxValue());
136 bool changed = ImGui::SliderFloat(label, &value, min, max,
format, flags);
138 if (changed)
setting.setFloat(value);
154 bool changed = ImGui::InputText(label, &value, ImGuiInputTextFlags_EnterReturnsTrue) || ImGui::IsItemDeactivatedAfterEdit();
170 for (const auto& entry : enumSetting->getMap()) {
171 bool selected = entry.name == current;
172 if (const auto& display = displayValue(entry.name);
173 ImGui::Selectable(display.c_str(), selected)) {
175 setting.setValue(TclObject(entry.name));
176 } catch (MSXException&) {
180 if (auto it = ranges::find(toolTips, entry.name, &EnumToolTip::value);
181 it != toolTips.end()) {
182 simpleToolTip(it->tip);
194 std::string name(
setting.getBaseName());
200 std::string name(
setting.getBaseName());
205 std::string name(
setting.getBaseName());
206 auto current =
setting.getValue().getString();
208 for (const auto& value : setting.getPossibleValues()) {
209 bool selected = value == current;
210 if (ImGui::Selectable(std::string(value).c_str(), selected)) {
212 setting.setValue(TclObject(value));
213 } catch (MSXException&) {
224 const char* p = itemsSeparatedByZeros;
227 if (item == 0)
return p;
237 auto hours = int(time * (1.0 / 3600.0));
238 time -= double(hours * 3600);
239 auto minutes = int(time * (1.0 / 60.0));
240 time -= double(minutes * 60);
241 auto seconds = int(time);
242 time -= double(seconds);
243 auto hundreds = int(100.0 * time);
245 std::string result =
"00:00:00.00";
246 auto insert = [&](
size_t pos,
unsigned value) {
248 result[pos + 0] = char(
'0' + (value / 10));
249 result[pos + 1] = char(
'0' + (value % 10));
251 insert(0, hours % 100);
260 const auto& io = ImGui::GetIO();
261 auto step = io.DeltaTime / period;
262 if (target > current) {
263 return std::min(target, current + step);
265 return std::max(target, current - step);
272 if (info.command != command)
continue;
273 if (
const auto* keyDown = std::get_if<KeyDownEvent>(&info.event)) {
275 auto modifiers = keyDown->getModifiers();
276 if (modifiers & KMOD_CTRL)
strAppend(result,
"CTRL+");
277 if (modifiers & KMOD_SHIFT)
strAppend(result,
"SHIFT+");
278 if (modifiers & KMOD_ALT)
strAppend(result,
"ALT+");
279 if (modifiers & KMOD_GUI)
strAppend(result,
"GUI+");
280 strAppend(result, SDL_GetKeyName(keyDown->getKeyCode()));
287[[nodiscard]]
static std::string_view superName()
289 return ImGui::GetIO().ConfigMacOSXBehaviors ?
"Cmd+" :
"Super+";
294 int keyCode =
ImGuiKey2SDL(ImGuiKey(keyChord & ~ImGuiMod_Mask_));
295 const auto* name = SDL_GetKeyName(keyCode);
296 if (!name || (*name ==
'\0'))
return "None";
298 (keyChord & ImGuiMod_Ctrl ?
"Ctrl+" :
""),
299 (keyChord & ImGuiMod_Shift ?
"Shift+" :
""),
300 (keyChord & ImGuiMod_Alt ?
"Alt+" :
""),
301 (keyChord & ImGuiMod_Super ? superName() :
""),
307 if (name ==
"None")
return ImGuiKey_None;
310 auto [modifiers, key] = [&]() -> std::pair<std::string_view, std::string_view> {
311 if (
auto pos = name.find_last_of(
'+'); pos == std::string_view::npos) {
312 return {std::string_view{}, name};
314 return {name.substr(0, pos + 1), name.substr(pos + 1)};
318 SDL_Keycode keyCode = SDL_GetKeyFromName(std::string(key).c_str());
319 if (keyCode == SDLK_UNKNOWN)
return {};
321 auto contains = [](std::string_view haystack, std::string_view needle) {
323 return haystack.find(needle) != std::string_view::npos;
325 ImGuiKeyChord keyMods =
326 (
contains(modifiers,
"Ctrl+" ) ? ImGuiMod_Ctrl : 0) |
327 (
contains(modifiers,
"Shift+") ? ImGuiMod_Shift : 0) |
328 (
contains(modifiers,
"Alt+" ) ? ImGuiMod_Alt : 0) |
329 (
contains(modifiers, superName()) ? ImGuiMod_Super : 0);
337 bool light = style == 1;
349 imColors[size_t(
TEXT )] = ImGui::GetColorU32(ImGuiCol_Text);
virtual void setValue(const TclObject &value)=0
Change the value of this setting to the given value.
virtual const TclObject & getValue() const =0
Get current value as a TclObject.
virtual TclObject getDefaultValue() const =0
Get the default value of this setting.
std::string_view getBaseName() const
A Setting with a floating point value.
const auto & getGlobalBindings() const
A Setting with an integer value.
zstring_view getString() const
Like std::string_view, but with the extra guarantee that it refers to a zero-terminated string.
constexpr const char * c_str() const
auto CalcTextSize(std::string_view str)
void TextUnformatted(const std::string &str)
void PopupContextItem(const char *str_id, ImGuiPopupFlags popup_flags, std::invocable<> auto next)
void Combo(const char *label, const char *preview_value, ImGuiComboFlags flags, std::invocable<> auto next)
void StyleColor(bool active, Args &&...args)
void format(SectorAccessibleDisk &disk, MSXBootSectorType bootType)
Format the given disk (= a single partition).
This file implemented 3 utility functions:
bool Checkbox(const HotKey &hotKey, BooleanSetting &setting)
bool SliderFloat(FloatSetting &setting, const char *format, ImGuiSliderFlags flags)
std::string formatTime(double time)
std::span< const EnumToolTip > EnumToolTips
bool SliderInt(IntegerSetting &setting, ImGuiSliderFlags flags)
void drawURL(std::string_view text, zstring_view url)
void ComboBox(const char *label, Setting &setting, function_ref< std::string(const std::string &)> displayValue, EnumToolTips toolTips)
void simpleToolTip(std::string_view desc)
std::string getShortCutForCommand(const HotKey &hotkey, std::string_view command)
ImGuiKey SDLKey2ImGui(SDL_Keycode sdl)
std::array< ImU32, size_t(imColor::NUM_COLORS)> imColors
void HelpMarker(std::string_view desc)
SDL_Keycode ImGuiKey2SDL(ImGuiKey imgui)
bool InputText(Setting &setting)
std::optional< ImGuiKeyChord > parseKeyChord(std::string_view name)
const char * getComboString(int item, const char *itemsSeparatedByZeros)
void setColors(int style)
std::string getKeyChordName(ImGuiKeyChord keyChord)
float calculateFade(float current, float target, float period)
constexpr bool contains(ITER first, ITER last, const VAL &val)
Check if a range contains a given value, using linear search.
void strAppend(std::string &result, Ts &&...ts)
std::string operator()(const Setting &setting) const