diff --git a/src/frontend/AudioSettings.cpp b/src/frontend/AudioSettings.cpp index e3e5dee5..979456ea 100644 --- a/src/frontend/AudioSettings.cpp +++ b/src/frontend/AudioSettings.cpp @@ -1,44 +1,44 @@ #include -AudioSettings::AudioSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) { - lockChannels->setChecked(JSONGetField(settings, "audio", "lock")); - volumeL->setValue(JSONGetField(settings, "audio", "volumeL") * 100); - volumeR->setValue(JSONGetField(settings, "audio", "volumeR") * 100); - volumeL->setRange(0, 100); - volumeR->setRange(0, 100); - - connect(lockChannels.get(), &QCheckBox::stateChanged, this, [&]() { - JSONSetField(settings, "audio", "lock", lockChannels->isChecked()); - if (lockChannels->isChecked()) { - volumeR->setValue(volumeL->value()); - } - - emit modified(); - }); - - connect(volumeL.get(), &QSlider::valueChanged, this, [&]() { - JSONSetField(settings, "audio", "volumeL", float(volumeL->value()) / 100.f); - if (lockChannels->isChecked()) { - volumeR->setValue(volumeL->value()); - JSONSetField(settings, "audio", "volumeR", float(volumeL->value()) / 100.f); - } - emit modified(); - }); - - connect(volumeR.get(), &QSlider::valueChanged, this, [&]() { - if (!lockChannels->isChecked()) { - JSONSetField(settings, "audio", "volumeR", float(volumeR->value()) / 100.f); - } - emit modified(); - }); - - mainLayout->addWidget(labelLock.get()); - mainLayout->addWidget(lockChannels.get()); - volLayout->addWidget(labelL.get()); - volLayout->addWidget(volumeL.get()); - volLayout->addWidget(labelR.get()); - volLayout->addWidget(volumeR.get()); - mainLayout->addLayout(volLayout.get()); - mainLayout->addStretch(); - setLayout(mainLayout.get()); +AudioSettings::AudioSettings(nlohmann::json &settings) : settings(settings) { + lockChannels.setChecked(JSONGetField(settings, "audio", "lock")); + volumeL.setValue(JSONGetField(settings, "audio", "volumeL") * 100); + volumeR.setValue(JSONGetField(settings, "audio", "volumeR") * 100); } + +bool AudioSettings::render() { + if(lockChannels.render()) { + auto isChecked = lockChannels.isChecked(); + JSONSetField(settings, "audio", "lock", isChecked); + if (isChecked) { + volumeR.setValue(volumeL.getValue()); + } + + modified = true; + } + + ImGui::SameLine(); + + if(volumeL.render()) { + float valueL = volumeL.getValue(); + JSONSetField(settings, "audio", "volumeL", float(valueL) / 100.f); + if (lockChannels.isChecked()) { + volumeR.setValue(valueL); + JSONSetField(settings, "audio", "volumeR", float(valueL) / 100.f); + } + + modified = true; + } + + ImGui::SameLine(); + + if(volumeR.render()) { + if (!lockChannels.isChecked()) { + JSONSetField(settings, "audio", "volumeR", float(volumeR.getValue()) / 100.f); + } + + modified = true; + } + + return modified; +} \ No newline at end of file diff --git a/src/frontend/AudioSettings.hpp b/src/frontend/AudioSettings.hpp index 94f05a84..33caa863 100644 --- a/src/frontend/AudioSettings.hpp +++ b/src/frontend/AudioSettings.hpp @@ -1,17 +1,17 @@ #pragma once #include +#include +#include class AudioSettings final { - //std::unique_ptr lockChannels = std::make_unique(); - //std::unique_ptr labelLock = std::make_unique("Lock channels:"); - //std::unique_ptr labelL = std::make_unique("Volume L"); - //std::unique_ptr labelR = std::make_unique("Volume R"); - //std::unique_ptr mainLayout = std::make_unique(); - //std::unique_ptr volLayout = std::make_unique(); - //Q_OBJECT + gui::Checkbox lockChannels{"Lock channels:", false}; + bool modified = false; public: - //std::unique_ptr volumeL = std::make_unique(Qt::Horizontal), - // volumeR = std::make_unique(Qt::Horizontal); + gui::SliderFloat volumeL{"Volume L", 0.f, 100.f, 0.f}; + gui::SliderFloat volumeR{"Volume R", 0.f, 100.f, 0.f}; explicit AudioSettings(nlohmann::json &); + bool render(); + void setModified(bool v) { modified = v; } + bool getModified() { return modified; } nlohmann::json &settings; }; diff --git a/src/frontend/CPUSettings.cpp b/src/frontend/CPUSettings.cpp index 5a709c36..0ffbe9d8 100644 --- a/src/frontend/CPUSettings.cpp +++ b/src/frontend/CPUSettings.cpp @@ -2,30 +2,22 @@ #include #include -CPUSettings::CPUSettings(nlohmann::json &settings) : QWidget(nullptr), settings(settings) { - cpuTypes->addItems({ - "Interpreter" //, "Dynamic Recompiler" - }); +CPUSettings::CPUSettings(nlohmann::json &settings) : settings(settings) { if (JSONGetField(settings, "cpu", "type") == "jit") { - cpuTypes->setCurrentIndex(1); + cpuTypes.setCurrentIndex(1); } else { - cpuTypes->setCurrentIndex(0); + cpuTypes.setCurrentIndex(0); } +} - connect(cpuTypes.get(), &QComboBox::currentIndexChanged, this, [&]() { - if (cpuTypes->currentIndex() == 0) { +bool CPUSettings::render() { + if(cpuTypes.render()) { + if(cpuTypes.getCurrentIndex() == 0) { JSONSetField(settings, "cpu", "type", "interpreter"); - //} else if (cpuTypes->currentIndex() == 1) { - // JSONSetField(settings, "cpu", "type", "jit"); } else { - Util::panic("Impossible CPU type!"); + Util::panic("JIT is unfinished and currently not supported!"); } - emit modified(); - }); - - mainLayout->addWidget(label.get()); - mainLayout->addWidget(cpuTypes.get()); - mainLayout->addStretch(); - setLayout(mainLayout.get()); + modified = true; + } } diff --git a/src/frontend/CPUSettings.hpp b/src/frontend/CPUSettings.hpp index b22ce5a1..855de175 100644 --- a/src/frontend/CPUSettings.hpp +++ b/src/frontend/CPUSettings.hpp @@ -1,12 +1,13 @@ #pragma once #include +#include class CPUSettings final { - //std::unique_ptr cpuTypes = std::make_unique(); - //std::unique_ptr label = std::make_unique("CPU type:"); - //std::unique_ptr mainLayout = std::make_unique(); - //Q_OBJECT + gui::Combobox cpuTypes{"CPU type:", {"Interpreter" //, "Dynamic Recompiler" + }}; + bool modified = false; public: + bool render(); explicit CPUSettings(nlohmann::json &); nlohmann::json &settings; }; diff --git a/src/frontend/Debugger.cpp b/src/frontend/Debugger.cpp index 0964ec2a..f1a2a7dd 100644 --- a/src/frontend/Debugger.cpp +++ b/src/frontend/Debugger.cpp @@ -1,6 +1,7 @@ #include -Debugger::Debugger() : QWidget(nullptr) { +Debugger::Debugger() { + /* disassembly->setWindowTitle("Disassembly"); disassembly->setFeatures(QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); codeView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -18,4 +19,5 @@ Debugger::Debugger() : QWidget(nullptr) { setLayout(verLayout.get()); // connect(codeView.get(), &QTreeView::activated, this, ); + */ } diff --git a/src/frontend/ImGuiImpl/Checkbox.hpp b/src/frontend/ImGuiImpl/Checkbox.hpp index 6a5efaff..306070a7 100644 --- a/src/frontend/ImGuiImpl/Checkbox.hpp +++ b/src/frontend/ImGuiImpl/Checkbox.hpp @@ -1,6 +1,16 @@ #pragma once #include +#include namespace gui { - +struct Checkbox { + Checkbox(const std::string& label, bool def = false) : val(def), label(label) {} + + void setChecked(bool v) { val = v; } + bool render() { return ImGui::Checkbox(label.c_str(), &val); } + bool isChecked() { return val; } +private: + bool val = false; + std::string label = ""; +}; } \ No newline at end of file diff --git a/src/frontend/ImGuiImpl/Combobox.hpp b/src/frontend/ImGuiImpl/Combobox.hpp new file mode 100644 index 00000000..d12d8087 --- /dev/null +++ b/src/frontend/ImGuiImpl/Combobox.hpp @@ -0,0 +1,46 @@ +#pragma once +#include +#include +#include + +namespace gui { +struct Combobox { + Combobox(std::string label, const std::vector& items, std::string preview = "") : label(label), items(items), preview(preview) {} + + bool render() { + const char* _preview = ""; + + if(preview != "") { + _preview = preview.c_str(); + } else { + _preview = items[current_index].c_str(); + } + + bool changed = false; + + if (ImGui::BeginCombo(label.c_str(), _preview)) { + for (int n = 0; n < items.size(); n++) { + const bool is_selected = ((current_index) == n); + if (ImGui::Selectable(items[n].c_str(), is_selected)) + { + current_index = n; + changed = true; + } + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + } + + return changed; + } + + void setCurrentIndex(int v) { current_index = v; } + int getCurrentIndex() { return current_index; } +private: + const std::vector& items; + std::string label, preview; + int current_index = 0; +}; +} \ No newline at end of file diff --git a/src/frontend/ImGuiImpl/Slider.hpp b/src/frontend/ImGuiImpl/Slider.hpp new file mode 100644 index 00000000..ac6c49bd --- /dev/null +++ b/src/frontend/ImGuiImpl/Slider.hpp @@ -0,0 +1,53 @@ +#pragma once +#include +#include + +namespace gui { +template +struct Slider { + Slider(const std::string& label, T min = 0, T max = 0, T default = 0) + : val(default), label(label), min(min), max(max) { } + + void setValue(T v) { val = v; } + bool render() { + return ImGui::SliderScalarN(label.c_str(), type_to_imgui(), (void*)&val, 1, (void*)&min, (void*)&max); + } + T getValue() { return val; } +private: + constexpr ImGuiDataType_ type_to_imgui() { + if constexpr(std::is_same_v) { + return ImGuiDataType_S8; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_U8; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_S16; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_U16; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_S32; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_U32; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_S64; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_U64; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_Float; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_Double; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_Bool; + } else if constexpr(std::is_same_v) { + return ImGuiDataType_String; + } else { + return ImGuiDataType_COUNT; + } + } + + T val{}, min{}, max{}; + std::string label = ""; +}; + +using SliderFloat = Slider; +using SliderInt = Slider; +} \ No newline at end of file