#include #include #include #include #include #include #ifndef IMGUI_DEFINE_MATH_OPERATORS #define IMGUI_DEFINE_MATH_OPERATORS #endif #include 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(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(0, freq); int i = 11; for (uint64_t f = freq; i >= 0; i--) { digits[i] = f % 10; f -= digits[i]; f /= 10; } frequency = freq; }