refactor: extract Clicked() + DrawPanelBox() sidebar widget helpers

Collapse the repeated 'CheckCollisionPointRec + IsMouseButtonPressed' click
test and the 'DrawRectangleRec + DrawRectangleLinesEx' panel chrome into two
helpers used across the sidebar buttons. Pure readability; render output is
pixel-identical (verified AE=0 vs baseline).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-25 08:59:08 -07:00
parent c75e014b88
commit 53f7fa6047
+38 -36
View File
@@ -14,6 +14,19 @@
static void DrawSlider(Rectangle bounds, float value); static void DrawSlider(Rectangle bounds, float value);
static bool UpdateSlider(Rectangle bounds, float* value); static bool UpdateSlider(Rectangle bounds, float* value);
// True if the rect was left-clicked this frame (hovered + button pressed).
static bool Clicked(Rectangle r)
{
return CheckCollisionPointRec(GetMousePosition(), r) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON);
}
// The ubiquitous "filled rectangle + 1px border" panel/button chrome.
static void DrawPanelBox(Rectangle r, Color fill, Color border)
{
DrawRectangleRec(r, fill);
DrawRectangleLinesEx(r, 1, border);
}
// ===== File browser ===== // ===== File browser =====
void FreeBrowserFiles(void) void FreeBrowserFiles(void)
{ {
@@ -335,35 +348,32 @@ void DrawSidebar(void)
DrawTextScaled(TextFormat("FFT: %d (%.1f Hz/bin)", app.fftSize, (float)app.signal.sampleRate / app.fftSize), x, y, 14, LIGHTGRAY); y += 20 * scale; DrawTextScaled(TextFormat("FFT: %d (%.1f Hz/bin)", app.fftSize, (float)app.signal.sampleRate / app.fftSize), x, y, 14, LIGHTGRAY); y += 20 * scale;
Rectangle fftMinus = { x, y, 30 * scale, 25 * scale }; Rectangle fftMinus = { x, y, 30 * scale, 25 * scale };
Rectangle fftPlus = { x + sidebarWidth - 40 * scale, y, 30 * scale, 25 * scale }; Rectangle fftPlus = { x + sidebarWidth - 40 * scale, y, 30 * scale, 25 * scale };
if (CheckCollisionPointRec(GetMousePosition(), fftMinus) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(fftMinus)) {
int newFFT = app.fftSize / 2; int newFFT = app.fftSize / 2;
if (newFFT >= FFT_SIZE_MIN) { if (newFFT >= FFT_SIZE_MIN) {
ChangeFFTSize(newFFT); ChangeFFTSize(newFFT);
} }
} }
if (CheckCollisionPointRec(GetMousePosition(), fftPlus) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(fftPlus)) {
int newFFT = app.fftSize * 2; int newFFT = app.fftSize * 2;
if (newFFT <= FFT_SIZE_MAX) { if (newFFT <= FFT_SIZE_MAX) {
ChangeFFTSize(newFFT); ChangeFFTSize(newFFT);
} }
} }
DrawRectangleRec(fftMinus, (Color){ 50, 50, 60, 255 }); DrawPanelBox(fftMinus, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(fftMinus, 1, GRAY);
DrawTextScaled("-", fftMinus.x + 12 * scale, fftMinus.y + 5 * scale, 18, WHITE); DrawTextScaled("-", fftMinus.x + 12 * scale, fftMinus.y + 5 * scale, 18, WHITE);
DrawRectangleRec(fftPlus, (Color){ 50, 50, 60, 255 }); DrawPanelBox(fftPlus, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(fftPlus, 1, GRAY);
DrawTextScaled("+", fftPlus.x + 10 * scale, fftPlus.y + 5 * scale, 18, WHITE); DrawTextScaled("+", fftPlus.x + 10 * scale, fftPlus.y + 5 * scale, 18, WHITE);
y += 32 * scale; y += 32 * scale;
// Amplitude scale mode toggle (Relative dynamic range vs Absolute dBFS) // Amplitude scale mode toggle (Relative dynamic range vs Absolute dBFS)
Rectangle scaleBtn = { x, y, sidebarWidth - 10 * scale, 22 * scale }; Rectangle scaleBtn = { x, y, sidebarWidth - 10 * scale, 22 * scale };
if (CheckCollisionPointRec(GetMousePosition(), scaleBtn) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(scaleBtn)) {
app.amplitudeMode = (app.amplitudeMode == SCALE_RELATIVE) ? SCALE_ABSOLUTE : SCALE_RELATIVE; app.amplitudeMode = (app.amplitudeMode == SCALE_RELATIVE) ? SCALE_ABSOLUTE : SCALE_RELATIVE;
AutoScaleAmplitude(&app.stft); // re-derive floor/ceiling for the new mode AutoScaleAmplitude(&app.stft); // re-derive floor/ceiling for the new mode
needsRegen = true; needsRegen = true;
} }
DrawRectangleRec(scaleBtn, (Color){ 50, 50, 60, 255 }); DrawPanelBox(scaleBtn, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(scaleBtn, 1, GRAY);
DrawTextScaled(app.amplitudeMode == SCALE_ABSOLUTE ? "Scale: Absolute (dBFS)" : "Scale: Relative", DrawTextScaled(app.amplitudeMode == SCALE_ABSOLUTE ? "Scale: Absolute (dBFS)" : "Scale: Relative",
scaleBtn.x + 8 * scale, scaleBtn.y + 4 * scale, 13, WHITE); scaleBtn.x + 8 * scale, scaleBtn.y + 4 * scale, 13, WHITE);
y += 30 * scale; y += 30 * scale;
@@ -395,13 +405,12 @@ void DrawSidebar(void)
// Colormap dropdown // Colormap dropdown
DrawTextScaled("Colormap:", x, y, 14, LIGHTGRAY); y += 20 * scale; DrawTextScaled("Colormap:", x, y, 14, LIGHTGRAY); y += 20 * scale;
Rectangle cmapButton = { x, y, sidebarWidth - 10 * scale, 25 * scale }; Rectangle cmapButton = { x, y, sidebarWidth - 10 * scale, 25 * scale };
if (CheckCollisionPointRec(GetMousePosition(), cmapButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(cmapButton)) {
app.colormap = (ColormapType)((app.colormap + 1) % COLORMAP_COUNT); app.colormap = (ColormapType)((app.colormap + 1) % COLORMAP_COUNT);
GenerateColormapTexture(); GenerateColormapTexture();
needsRegen = true; needsRegen = true;
} }
DrawRectangleRec(cmapButton, (Color){ 50, 50, 60, 255 }); DrawPanelBox(cmapButton, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(cmapButton, 1, GRAY);
DrawTextScaled(ColormapName(app.colormap), cmapButton.x + 10 * scale, cmapButton.y + 6 * scale, 14, WHITE); DrawTextScaled(ColormapName(app.colormap), cmapButton.x + 10 * scale, cmapButton.y + 6 * scale, 14, WHITE);
DrawTexturePro(colormapTexture, (Rectangle){ 0, 0, 256, 1 }, DrawTexturePro(colormapTexture, (Rectangle){ 0, 0, 256, 1 },
(Rectangle){ cmapButton.x + cmapButton.width - 60 * scale, cmapButton.y + 5 * scale, 50 * scale, 15 * scale }, (Rectangle){ cmapButton.x + cmapButton.width - 60 * scale, cmapButton.y + 5 * scale, 50 * scale, 15 * scale },
@@ -410,28 +419,26 @@ void DrawSidebar(void)
// Grid toggle // Grid toggle
Rectangle gridCheck = { x, y, 18 * scale, 18 * scale }; Rectangle gridCheck = { x, y, 18 * scale, 18 * scale };
if (CheckCollisionPointRec(GetMousePosition(), gridCheck) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(gridCheck)) {
app.showGrid = !app.showGrid; app.showGrid = !app.showGrid;
} }
DrawRectangleRec(gridCheck, app.showGrid ? BLUE : DARKGRAY); DrawPanelBox(gridCheck, app.showGrid ? BLUE : DARKGRAY, WHITE);
DrawRectangleLinesEx(gridCheck, 1, WHITE);
DrawTextScaled("Show Grid", x + 25 * scale, y + 2 * scale, 14, LIGHTGRAY); y += 28 * scale; DrawTextScaled("Show Grid", x + 25 * scale, y + 2 * scale, 14, LIGHTGRAY); y += 28 * scale;
// File loading // File loading
DrawTextScaled("File:", x, y, 14, LIGHTGRAY); y += 20 * scale; DrawTextScaled("File:", x, y, 14, LIGHTGRAY); y += 20 * scale;
Rectangle fileButton = { x, y, sidebarWidth - 10 * scale, 25 * scale }; Rectangle fileButton = { x, y, sidebarWidth - 10 * scale, 25 * scale };
if (CheckCollisionPointRec(GetMousePosition(), fileButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(fileButton)) {
app.showFileBrowser = true; app.showFileBrowser = true;
ScanDirectory(GetWorkingDirectory()); ScanDirectory(GetWorkingDirectory());
} }
DrawRectangleRec(fileButton, (Color){ 50, 50, 60, 255 }); DrawPanelBox(fileButton, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(fileButton, 1, GRAY);
DrawTextScaled("Open File Browser (O)", fileButton.x + 10 * scale, fileButton.y + 6 * scale, 14, WHITE); DrawTextScaled("Open File Browser (O)", fileButton.x + 10 * scale, fileButton.y + 6 * scale, 14, WHITE);
y += 38 * scale; y += 38 * scale;
// Playback // Playback
Rectangle playButton = { x, y, sidebarWidth - 10 * scale, 35 * scale }; Rectangle playButton = { x, y, sidebarWidth - 10 * scale, 35 * scale };
if (CheckCollisionPointRec(GetMousePosition(), playButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(playButton)) {
if (app.isPlaying && AudioPlaybackSound.frameCount > 0) { if (app.isPlaying && AudioPlaybackSound.frameCount > 0) {
StopSound(AudioPlaybackSound); StopSound(AudioPlaybackSound);
app.isPlaying = false; app.isPlaying = false;
@@ -443,54 +450,50 @@ void DrawSidebar(void)
} }
} }
const char* playText = app.isPlaying ? "STOP (SPACE)" : "PLAY (SPACE)"; const char* playText = app.isPlaying ? "STOP (SPACE)" : "PLAY (SPACE)";
DrawRectangleRec(playButton, app.isPlaying ? (Color){ 120, 40, 40, 255 } : (Color){ 40, 100, 40, 255 }); DrawPanelBox(playButton, app.isPlaying ? (Color){ 120, 40, 40, 255 } : (Color){ 40, 100, 40, 255 },
DrawRectangleLinesEx(playButton, 1, app.isPlaying ? RED : GREEN); app.isPlaying ? RED : GREEN);
DrawTextScaled(playText, playButton.x + 10 * scale, playButton.y + 12 * scale, 14, WHITE); DrawTextScaled(playText, playButton.x + 10 * scale, playButton.y + 12 * scale, 14, WHITE);
y += 48 * scale; y += 48 * scale;
// Fullscreen toggle // Fullscreen toggle
Rectangle fsButton = { x, y, sidebarWidth - 10 * scale, 25 * scale }; Rectangle fsButton = { x, y, sidebarWidth - 10 * scale, 25 * scale };
bool isFullscreen = IsWindowFullscreen(); bool isFullscreen = IsWindowFullscreen();
if (CheckCollisionPointRec(GetMousePosition(), fsButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(fsButton)) {
ToggleFullscreen(); ToggleFullscreen();
} }
DrawRectangleRec(fsButton, isFullscreen ? (Color){ 40, 80, 120, 255 } : (Color){ 50, 50, 60, 255 }); DrawPanelBox(fsButton, isFullscreen ? (Color){ 40, 80, 120, 255 } : (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(fsButton, 1, GRAY);
DrawTextScaled(isFullscreen ? "Exit Fullscreen (F11)" : "Fullscreen (F11)", fsButton.x + 10 * scale, fsButton.y + 6 * scale, 14, WHITE); DrawTextScaled(isFullscreen ? "Exit Fullscreen (F11)" : "Fullscreen (F11)", fsButton.x + 10 * scale, fsButton.y + 6 * scale, 14, WHITE);
y += 38 * scale; y += 38 * scale;
// Reset/Clear buttons // Reset/Clear buttons
Rectangle resetButton = { x, y, (sidebarWidth - 15 * scale) / 2, 25 * scale }; Rectangle resetButton = { x, y, (sidebarWidth - 15 * scale) / 2, 25 * scale };
if (CheckCollisionPointRec(GetMousePosition(), resetButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(resetButton)) {
app.timeSelectionStart = app.viewStart; app.timeSelectionStart = app.viewStart;
app.timeSelectionEnd = app.viewEnd; app.timeSelectionEnd = app.viewEnd;
app.freqSelectionStart = 0.0f; app.freqSelectionStart = 0.0f;
app.freqSelectionEnd = 1.0f; app.freqSelectionEnd = 1.0f;
} }
DrawRectangleRec(resetButton, (Color){ 80, 50, 50, 255 }); DrawPanelBox(resetButton, (Color){ 80, 50, 50, 255 }, RED);
DrawRectangleLinesEx(resetButton, 1, RED);
DrawTextScaled("Reset Sel (R)", resetButton.x + 10 * scale, resetButton.y + 6 * scale, 14, WHITE); DrawTextScaled("Reset Sel (R)", resetButton.x + 10 * scale, resetButton.y + 6 * scale, 14, WHITE);
Rectangle clearButton = { x + resetButton.width + 5 * scale, y, (sidebarWidth - 15 * scale) / 2, 25 * scale }; Rectangle clearButton = { x + resetButton.width + 5 * scale, y, (sidebarWidth - 15 * scale) / 2, 25 * scale };
if (CheckCollisionPointRec(GetMousePosition(), clearButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(clearButton)) {
app.timeSelectionStart = 0.0f; app.timeSelectionStart = 0.0f;
app.timeSelectionEnd = 1.0f; app.timeSelectionEnd = 1.0f;
app.freqSelectionStart = 0.0f; app.freqSelectionStart = 0.0f;
app.freqSelectionEnd = 1.0f; app.freqSelectionEnd = 1.0f;
} }
DrawRectangleRec(clearButton, (Color){ 80, 50, 50, 255 }); DrawPanelBox(clearButton, (Color){ 80, 50, 50, 255 }, RED);
DrawRectangleLinesEx(clearButton, 1, RED);
DrawTextScaled("Clear (ESC)", clearButton.x + 10 * scale, clearButton.y + 6 * scale, 14, WHITE); DrawTextScaled("Clear (ESC)", clearButton.x + 10 * scale, clearButton.y + 6 * scale, 14, WHITE);
y += 38 * scale; y += 38 * scale;
// Export PNG // Export PNG
{ {
Rectangle exportButton = { x, y, sidebarWidth - 10 * scale, 30 * scale }; Rectangle exportButton = { x, y, sidebarWidth - 10 * scale, 30 * scale };
if (CheckCollisionPointRec(GetMousePosition(), exportButton) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(exportButton)) {
ExportPNG(&app, app.exportDir); ExportPNG(&app, app.exportDir);
} }
DrawRectangleRec(exportButton, (Color){ 40, 60, 80, 255 }); DrawPanelBox(exportButton, (Color){ 40, 60, 80, 255 }, CYAN);
DrawRectangleLinesEx(exportButton, 1, CYAN);
DrawTextScaled("Export PNG (E)", exportButton.x + 10 * scale, exportButton.y + 7 * scale, 14, WHITE); DrawTextScaled("Export PNG (E)", exportButton.x + 10 * scale, exportButton.y + 7 * scale, 14, WHITE);
y += 35 * scale; y += 35 * scale;
@@ -518,11 +521,10 @@ void DrawSidebar(void)
// About / Help button // About / Help button
Rectangle aboutBtn = { x, y, sidebarWidth - 10 * scale, 24 * scale }; Rectangle aboutBtn = { x, y, sidebarWidth - 10 * scale, 24 * scale };
if (CheckCollisionPointRec(GetMousePosition(), aboutBtn) && IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) { if (Clicked(aboutBtn)) {
app.showAbout = true; app.showAbout = true;
} }
DrawRectangleRec(aboutBtn, (Color){ 50, 50, 60, 255 }); DrawPanelBox(aboutBtn, (Color){ 50, 50, 60, 255 }, GRAY);
DrawRectangleLinesEx(aboutBtn, 1, GRAY);
DrawTextScaled("About / Help (F1)", aboutBtn.x + 8 * scale, aboutBtn.y + 5 * scale, 13, WHITE); DrawTextScaled("About / Help (F1)", aboutBtn.x + 8 * scale, aboutBtn.y + 5 * scale, 13, WHITE);
y += 30 * scale; y += 30 * scale;