Fix the volume slider visual

This commit is contained in:
NeilClack
2026-08-13 15:17:20 -05:00
parent fe2c9ba6a5
commit e774fbfda9
2 changed files with 58 additions and 20 deletions
+56 -20
View File
@@ -7,23 +7,6 @@
namespace {
std::string buildVolumeBar(int volume_0_to_100) {
int totalBlocks = 10;
int filled = (volume_0_to_100 * totalBlocks + 50) / 100;
filled = std::clamp(filled, 0, totalBlocks);
std::string bar = "[";
for (int i = 0; i < totalBlocks; ++i) {
if (i < filled) {
bar += "\u2588"; // Solid block
} else {
bar += "\u2591"; // Light shade block
}
}
bar += "] " + std::to_string(volume_0_to_100) + "%";
return bar;
}
// Case-insensitive lexicographic comparison for alphabetical list ordering.
int ciCompare(const std::string& a, const std::string& b) {
size_t i = 0;
@@ -241,6 +224,8 @@ void AudioSettingsPage::destroyTextures() {
deviceText_.destroy();
statusMsgText_.destroy();
footerText_.destroy();
volumeLabelText_.destroy();
volumePercentText_.destroy();
for (auto& row : menuRows_) row.destroy();
menuRows_.clear();
@@ -561,8 +546,58 @@ void AudioSettingsPage::render(SDL_Renderer* renderer) {
: ((currentTrackIndex_ >= 0 && currentTrackIndex_ < static_cast<int>(tracks_.size()))
? tracks_[currentTrackIndex_].display_name : "Original Audio");
// Volume row is drawn specially: a fixed percentage label to the left
// of a full-width outlined bar whose solid fill tracks the volume.
int volume = state_->audio.getVolume();
SDL_Color volumeColor = (selectedItem_ == 0) ? yellow : white;
volumeLabelText_.ensure(renderer, fontBody_, "Volume:", volumeColor);
volumePercentText_.ensure(renderer, fontBody_, std::to_string(volume) + "%", volumeColor);
float labelX = 100.0f;
float textY = listY + (rowHeight - volumeLabelText_.height) / 2.0f;
if (volumeLabelText_.texture) {
SDL_FRect dst{labelX, textY, volumeLabelText_.width, volumeLabelText_.height};
SDL_RenderTexture(renderer, volumeLabelText_.texture, nullptr, &dst);
}
float pctX = labelX + volumeLabelText_.width + 12.0f;
if (volumePercentText_.texture) {
SDL_FRect dst{pctX, textY, volumePercentText_.width, volumePercentText_.height};
SDL_RenderTexture(renderer, volumePercentText_.texture, nullptr, &dst);
}
// The bar outline spans the remaining full width (right edge matching
// the menu's 100px right margin) and never moves: its left edge is
// reserved from the widest percentage text ("100%"). Only the fill
// grows and shrinks with the volume.
int widestPctW = 0;
TTF_GetStringSize(fontBody_, "100%", 0, &widestPctW, nullptr);
float barLeft = pctX + static_cast<float>(widestPctW) + 20.0f;
float barRight = fw - 100.0f;
float barTop = listY + (rowHeight - 24.0f) / 2.0f;
float barH = 24.0f;
float barW = barRight - barLeft;
SDL_SetRenderDrawColor(renderer, 150, 160, 180, 255);
SDL_FRect barOutline{barLeft, barTop, barW, barH};
SDL_RenderRect(renderer, &barOutline);
float fillW = barW * static_cast<float>(volume) / 100.0f;
if (fillW > 0.0f) {
SDL_SetRenderDrawColor(renderer, 0, 200, 120, 255);
SDL_FRect fill{barLeft + 1.0f, barTop + 1.0f, std::max(0.0f, fillW - 2.0f), barH - 2.0f};
SDL_RenderFillRect(renderer, &fill);
}
if (selectedItem_ == 0) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_FRect selLine{labelX, listY + volumeLabelText_.height + 2.0f, barRight - labelX, 6.0f};
SDL_RenderFillRect(renderer, &selLine);
}
listY += rowHeight;
std::vector<std::string> rowTexts = {
"Volume: " + buildVolumeBar(state_->audio.getVolume()),
"Output Device: [" + devName + "]",
"Audio Track: [" + trackName + "]",
std::string("Audio Status: [") + (state_->audio.isAudioEnabled() ? "ON" : "OFF") + "]",
@@ -571,13 +606,14 @@ void AudioSettingsPage::render(SDL_Renderer* renderer) {
if (menuRows_.size() != rowTexts.size()) menuRows_.resize(rowTexts.size());
for (int i = 0; i < static_cast<int>(rowTexts.size()); ++i) {
SDL_Color color = (selectedItem_ == i) ? yellow : white;
int rowIndex = i + 1; // row 0 is the volume slider
SDL_Color color = (selectedItem_ == rowIndex) ? yellow : white;
menuRows_[i].ensure(renderer, fontBody_, rowTexts[i], color);
if (!menuRows_[i].texture) { listY += rowHeight; continue; }
SDL_FRect dst{100.0f, listY, menuRows_[i].width, menuRows_[i].height};
SDL_RenderTexture(renderer, menuRows_[i].texture, nullptr, &dst);
if (selectedItem_ == i) {
if (selectedItem_ == rowIndex) {
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_FRect selLine{100.0f, listY + menuRows_[i].height + 2.0f, menuRows_[i].width, 6.0f};
SDL_RenderFillRect(renderer, &selLine);
+2
View File
@@ -66,6 +66,8 @@ private:
CachedText deviceText_;
CachedText statusMsgText_;
CachedText footerText_;
CachedText volumeLabelText_;
CachedText volumePercentText_;
std::vector<CachedText> menuRows_;
CachedText modalTitleText_;