SDRPlusPlus/core/src/gui/widgets/frequency_select.cpp

228 wiersze
7.2 KiB
C++

#include <gui/widgets/frequency_select.h>
#include <config.h>
#include <gui/style.h>
#include <gui/gui.h>
#include <backend.h>
#include <keybinds.h>
#ifndef IMGUI_DEFINE_MATH_OPERATORS
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include <imgui/imgui_internal.h>
bool isInArea(ImVec2 val, ImVec2 min, ImVec2 max) {
return val.x >= min.x && val.x < max.x && val.y >= min.y && val.y < max.y;
}
FrequencySelect::FrequencySelect() {
}
void FrequencySelect::init() {
for (int i = 0; i < 12; i++) {
digits[i] = 0;
}
}
void FrequencySelect::onPosChange() {
ImVec2 digitSz = ImGui::CalcTextSize("0");
ImVec2 commaSz = ImGui::CalcTextSize(".");
int digitHeight = digitSz.y;
int digitWidth = digitSz.x;
int commaOffset = 0;
for (int i = 0; i < 12; i++) {
digitTopMins[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y);
digitBottomMins[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y + (digitHeight / 2));
digitTopMaxs[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + digitWidth, widgetPos.y + (digitHeight / 2));
digitBottomMaxs[i] = ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + digitWidth, widgetPos.y + digitHeight);
if ((i + 1) % 3 == 0 && i < 11) {
commaOffset += commaSz.x;
}
}
}
void FrequencySelect::incrementDigit(int i) {
if (i < 0) {
return;
}
if (digits[i] < 9) {
digits[i]++;
}
else {
digits[i] = 0;
incrementDigit(i - 1);
}
frequencyChanged = true;
}
void FrequencySelect::decrementDigit(int i) {
if (i < 0) {
return;
}
if (digits[i] > 0) {
digits[i]--;
}
else {
if (i == 0) { return; }
// Check if there are non zero digits afterwards
bool otherNoneZero = false;
for (int j = i - 1; j >= 0; j--) {
if (digits[j] > 0) {
otherNoneZero = true;
break;
}
}
if (!otherNoneZero) { return; }
digits[i] = 9;
decrementDigit(i - 1);
}
frequencyChanged = true;
}
void FrequencySelect::moveCursorToDigit(int i) {
double xpos, ypos;
backend::getMouseScreenPos(xpos, ypos);
double nxpos = (digitTopMaxs[i].x + digitTopMins[i].x) / 2.0;
backend::setMouseScreenPos(nxpos, ypos);
}
void FrequencySelect::draw() {
auto window = ImGui::GetCurrentWindow();
widgetPos = ImGui::GetWindowContentRegionMin();
ImVec2 cursorPos = ImGui::GetCursorPos();
widgetPos.x += window->Pos.x + cursorPos.x;
ImGui::PushFont(style::bigFont);
ImVec2 digitSz = ImGui::CalcTextSize("0");
ImVec2 commaSz = ImGui::CalcTextSize(".");
widgetPos.y = cursorPos.y - ((digitSz.y / 2.0f) - ceilf(15 * style::uiScale) - 5);
if (widgetPos.x != lastWidgetPos.x || widgetPos.y != lastWidgetPos.y) {
lastWidgetPos = widgetPos;
onPosChange();
}
ImU32 disabledColor = ImGui::GetColorU32(ImGuiCol_Text, 0.3f);
ImU32 textColor = ImGui::GetColorU32(ImGuiCol_Text);
int digitWidth = digitSz.x;
int commaOffset = 0;
float textOffset = 11.0f * style::uiScale;
bool zeros = true;
ImGui::ItemSize(ImRect(digitTopMins[0], ImVec2(digitBottomMaxs[11].x + 15, digitBottomMaxs[11].y)));
for (int i = 0; i < 12; i++) {
if (digits[i] != 0) {
zeros = false;
}
sprintf(buf, "%d", digits[i]);
window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset, widgetPos.y),
zeros ? disabledColor : textColor, buf);
if ((i + 1) % 3 == 0 && i < 11) {
commaOffset += commaSz.x;
window->DrawList->AddText(ImVec2(widgetPos.x + (i * digitWidth) + commaOffset + textOffset, widgetPos.y),
zeros ? disabledColor : textColor, ".");
}
}
if (!gui::mainWindow.lockWaterfallControls) {
ImVec2 mousePos = ImGui::GetMousePos();
bool leftClick = ImGui::IsMouseClicked(ImGuiMouseButton_Left);
bool rightClick = ImGui::IsMouseClicked(ImGuiMouseButton_Right);
int mw = ImGui::GetIO().MouseWheel;
bool onDigit = false;
bool hovered = false;
for (int i = 0; i < 12; i++) {
onDigit = false;
if (isInArea(mousePos, digitTopMins[i], digitTopMaxs[i])) {
window->DrawList->AddRectFilled(digitTopMins[i], digitTopMaxs[i], IM_COL32(255, 0, 0, 75));
if (leftClick) {
incrementDigit(i);
}
onDigit = true;
}
if (isInArea(mousePos, digitBottomMins[i], digitBottomMaxs[i])) {
window->DrawList->AddRectFilled(digitBottomMins[i], digitBottomMaxs[i], IM_COL32(0, 0, 255, 75));
if (leftClick) {
decrementDigit(i);
}
onDigit = true;
}
if (onDigit) {
hovered = true;
if (rightClick || (ImGui::IsKeyPressed(KB_KEY_DEL) || ImGui::IsKeyPressed(KB_KEY_ENTER) || ImGui::IsKeyPressed(KB_KEY_KP_ENTER))) {
for (int j = i; j < 12; j++) {
digits[j] = 0;
}
frequencyChanged = true;
}
if (ImGui::IsKeyPressed(KB_KEY_UP)) {
incrementDigit(i);
}
if (ImGui::IsKeyPressed(KB_KEY_DOWN)) {
decrementDigit(i);
}
if ((ImGui::IsKeyPressed(KB_KEY_LEFT) || ImGui::IsKeyPressed(KB_KEY_BACKSPACE)) && i > 0) {
moveCursorToDigit(i - 1);
}
if (ImGui::IsKeyPressed(KB_KEY_RIGHT) && i < 11) {
moveCursorToDigit(i + 1);
}
auto chars = ImGui::GetIO().InputQueueCharacters;
// For each keyboard characters, type it
for (int j = 0; j < chars.Size; j++) {
if (chars[j] >= '0' && chars[j] <= '9') {
digits[i + j] = chars[j] - '0';
if ((i + j) < 11) { moveCursorToDigit(i + j + 1); }
frequencyChanged = true;
}
}
if (mw != 0) {
int count = abs(mw);
for (int j = 0; j < count; j++) {
mw > 0 ? incrementDigit(i) : decrementDigit(i);
}
}
}
}
digitHovered = hovered;
}
uint64_t freq = 0;
for (int i = 0; i < 12; i++) {
freq += digits[i] * pow(10, 11 - i);
}
uint64_t orig = freq;
freq = std::clamp<uint64_t>(freq, minFreq, maxFreq);
if (freq != orig && limitFreq) {
setFrequency(freq);
}
else {
frequency = orig;
}
ImGui::PopFont();
ImGui::SetCursorPosX(digitBottomMaxs[11].x + (17.0f * style::uiScale));
}
void FrequencySelect::setFrequency(int64_t freq) {
freq = std::max<int64_t>(0, freq);
int i = 11;
for (uint64_t f = freq; i >= 0; i--) {
digits[i] = f % 10;
f -= digits[i];
f /= 10;
}
frequency = freq;
}