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;
236 if (!time)
return "--:--:--.--";
237 auto remainingTime = *time;
238 assert(remainingTime >= 0.0);
239 auto hours = int(remainingTime * (1.0 / 3600.0));
240 remainingTime -= double(hours * 3600);
241 auto minutes = int(remainingTime * (1.0 / 60.0));
242 remainingTime -= double(minutes * 60);
243 auto seconds = int(remainingTime);
244 remainingTime -= double(seconds);
245 auto hundreds = int(100.0 * remainingTime);
247 std::string result =
"00:00:00.00";
248 auto insert = [&](
size_t pos,
unsigned value) {
250 result[pos + 0] = char(
'0' + (value / 10));
251 result[pos + 1] = char(
'0' + (value % 10));
253 insert(0, hours % 100);
262 const auto& io = ImGui::GetIO();
263 auto step = io.DeltaTime / period;
264 if (target > current) {
265 return std::min(target, current + step);
267 return std::max(target, current - step);
274 if (info.command != command)
continue;
275 if (
const auto* keyDown = std::get_if<KeyDownEvent>(&info.event)) {
277 auto modifiers = keyDown->getModifiers();
278 if (modifiers & KMOD_CTRL)
strAppend(result,
"CTRL+");
279 if (modifiers & KMOD_SHIFT)
strAppend(result,
"SHIFT+");
280 if (modifiers & KMOD_ALT)
strAppend(result,
"ALT+");
281 if (modifiers & KMOD_GUI)
strAppend(result,
"GUI+");
282 strAppend(result, SDL_GetKeyName(keyDown->getKeyCode()));
289[[nodiscard]]
static std::string_view superName()
291 return ImGui::GetIO().ConfigMacOSXBehaviors ?
"Cmd+" :
"Super+";
296 int keyCode =
ImGuiKey2SDL(ImGuiKey(keyChord & ~ImGuiMod_Mask_));
297 const auto* name = SDL_GetKeyName(keyCode);
298 if (!name || (*name ==
'\0'))
return "None";
300 (keyChord & ImGuiMod_Ctrl ?
"Ctrl+" :
""),
301 (keyChord & ImGuiMod_Shift ?
"Shift+" :
""),
302 (keyChord & ImGuiMod_Alt ?
"Alt+" :
""),
303 (keyChord & ImGuiMod_Super ? superName() :
""),
309 if (name ==
"None")
return ImGuiKey_None;
312 auto [modifiers, key] = [&]() -> std::pair<std::string_view, std::string_view> {
313 if (
auto pos = name.find_last_of(
'+'); pos == std::string_view::npos) {
314 return {std::string_view{}, name};
316 return {name.substr(0, pos + 1), name.substr(pos + 1)};
320 SDL_Keycode keyCode = SDL_GetKeyFromName(std::string(key).c_str());
321 if (keyCode == SDLK_UNKNOWN)
return {};
323 auto contains = [](std::string_view haystack, std::string_view needle) {
325 return haystack.find(needle) != std::string_view::npos;
327 ImGuiKeyChord keyMods =
328 (
contains(modifiers,
"Ctrl+" ) ? ImGuiMod_Ctrl : 0) |
329 (
contains(modifiers,
"Shift+") ? ImGuiMod_Shift : 0) |
330 (
contains(modifiers,
"Alt+" ) ? ImGuiMod_Alt : 0) |
331 (
contains(modifiers, superName()) ? ImGuiMod_Super : 0);
339 bool light = style == 1;
351 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::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)
std::string formatTime(std::optional< double > time)
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