refactor: centralize screen layout in ComputeLayout()
The spectrogram layout metrics (sidebar width, margins, freq-label width, scrollbar sizes, spectroHeight, viewBounds) were computed with identical formulas in three places — the input, selection, and render passes — so a layout tweak meant editing all three in sync (as the scope divider change just did). Introduce a Layout struct + ComputeLayout(); each site now unpacks from it into its existing locals, leaving every downstream coordinate reference untouched. Verified pixel-identical to the previous build (ImageMagick AE = 0). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+70
-48
@@ -62,6 +62,43 @@ static float ScopeDivider(void)
|
||||
return app.showScope ? app.dividerY : 1.0f;
|
||||
}
|
||||
|
||||
// Screen layout metrics, derived from window size + UI scale. Single source of
|
||||
// truth: the input, selection, and render passes all unpack from this so the
|
||||
// layout formulas live in exactly one place.
|
||||
typedef struct {
|
||||
float scale;
|
||||
float sidebarWidth;
|
||||
float labelHeight;
|
||||
float scrollbarHeight;
|
||||
float freqLabelWidth;
|
||||
float vScrollbarWidth;
|
||||
float topMargin;
|
||||
float bottomMargin;
|
||||
float spectroHeight; // height of the spectrogram (respects the scope divider)
|
||||
Rectangle viewBounds; // the spectrogram drawing area
|
||||
} Layout;
|
||||
|
||||
static Layout ComputeLayout(void)
|
||||
{
|
||||
Layout L;
|
||||
L.scale = GetUIScale();
|
||||
L.sidebarWidth = 320 * L.scale;
|
||||
L.labelHeight = 15 * L.scale;
|
||||
L.scrollbarHeight = 18 * L.scale;
|
||||
L.freqLabelWidth = 65 * L.scale;
|
||||
L.vScrollbarWidth = 18 * L.scale;
|
||||
L.topMargin = 50 * L.scale;
|
||||
L.bottomMargin = 10 * L.scale;
|
||||
L.spectroHeight = (GetScreenHeight() - L.topMargin - L.bottomMargin - L.labelHeight - L.scrollbarHeight - 10 * L.scale) * ScopeDivider();
|
||||
L.viewBounds = (Rectangle){
|
||||
L.sidebarWidth + L.freqLabelWidth,
|
||||
L.topMargin,
|
||||
GetScreenWidth() - L.sidebarWidth - L.freqLabelWidth - L.vScrollbarWidth - 20 * L.scale,
|
||||
L.spectroHeight
|
||||
};
|
||||
return L;
|
||||
}
|
||||
|
||||
// Reset all per-signal state after a new signal has been loaded into app.signal.
|
||||
// Drops the cached STFT/FFT-size cache and the on-screen textures so the main
|
||||
// loop recomputes from scratch (loadingPhase 0 handles the STFT (re)alloc).
|
||||
@@ -260,22 +297,17 @@ int main(int argc, char* argv[])
|
||||
// View controls
|
||||
if (app.loaded && !UiModalOpen()) {
|
||||
// Spectrogram area fills remaining window space (scaled)
|
||||
float viewScale = GetUIScale();
|
||||
float sidebarWidth = 320 * viewScale;
|
||||
float labelHeight = 15 * viewScale;
|
||||
float scrollbarHeight = 18 * viewScale;
|
||||
float freqLabelWidth = 65 * viewScale;
|
||||
float vScrollbarWidth = 18 * viewScale;
|
||||
float topMargin = 50 * viewScale;
|
||||
float bottomMargin = 10 * viewScale;
|
||||
|
||||
float spectroHeight = (GetScreenHeight() - topMargin - bottomMargin - labelHeight - scrollbarHeight - 10 * viewScale) * ScopeDivider();
|
||||
Rectangle viewBounds = {
|
||||
sidebarWidth + freqLabelWidth,
|
||||
topMargin,
|
||||
GetScreenWidth() - sidebarWidth - freqLabelWidth - vScrollbarWidth - 20 * viewScale,
|
||||
spectroHeight
|
||||
};
|
||||
Layout L = ComputeLayout();
|
||||
float viewScale = L.scale;
|
||||
float sidebarWidth = L.sidebarWidth;
|
||||
float labelHeight = L.labelHeight;
|
||||
float scrollbarHeight = L.scrollbarHeight;
|
||||
float freqLabelWidth = L.freqLabelWidth;
|
||||
float vScrollbarWidth = L.vScrollbarWidth;
|
||||
float topMargin = L.topMargin;
|
||||
float bottomMargin = L.bottomMargin;
|
||||
float spectroHeight = L.spectroHeight;
|
||||
Rectangle viewBounds = L.viewBounds;
|
||||
|
||||
// Zoom with mouse wheel (zooms both time and frequency to maintain aspect ratio)
|
||||
if (GetMousePosition().x > sidebarWidth + 5 && CheckCollisionPointRec(GetMousePosition(), viewBounds)) {
|
||||
@@ -478,22 +510,17 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
|
||||
// Selection: box select with LMB drag, right-click to clear
|
||||
float selScale = GetUIScale();
|
||||
float selSidebarWidth = 320 * selScale;
|
||||
float selLabelHeight = 15 * selScale;
|
||||
float selScrollbarHeight = 18 * selScale;
|
||||
float selFreqLabelWidth = 65 * selScale;
|
||||
float selVScrollbarWidth = 18 * selScale;
|
||||
float selTopMargin = 50 * selScale;
|
||||
float selBottomMargin = 10 * selScale;
|
||||
|
||||
float selSpectroHeight = (GetScreenHeight() - selTopMargin - selBottomMargin - selLabelHeight - selScrollbarHeight - 10.0f * selScale) * ScopeDivider();
|
||||
Rectangle selBounds = {
|
||||
selSidebarWidth + selFreqLabelWidth,
|
||||
selTopMargin,
|
||||
GetScreenWidth() - selSidebarWidth - selFreqLabelWidth - selVScrollbarWidth - 20.0f * selScale,
|
||||
selSpectroHeight
|
||||
};
|
||||
Layout selL = ComputeLayout();
|
||||
float selScale = selL.scale;
|
||||
float selSidebarWidth = selL.sidebarWidth;
|
||||
float selLabelHeight = selL.labelHeight;
|
||||
float selScrollbarHeight = selL.scrollbarHeight;
|
||||
float selFreqLabelWidth = selL.freqLabelWidth;
|
||||
float selVScrollbarWidth = selL.vScrollbarWidth;
|
||||
float selTopMargin = selL.topMargin;
|
||||
float selBottomMargin = selL.bottomMargin;
|
||||
float selSpectroHeight = selL.spectroHeight;
|
||||
Rectangle selBounds = selL.viewBounds;
|
||||
Vector2 mousePos = GetMousePosition();
|
||||
|
||||
// Calculate divider screen position (for hover detection)
|
||||
@@ -766,23 +793,18 @@ int main(int argc, char* argv[])
|
||||
ClearBackground((Color){ 30, 30, 30, 255 });
|
||||
|
||||
// Layout: sidebar on left, spectrogram on right (scaled)
|
||||
float renderScale = GetUIScale();
|
||||
float sidebarWidth = 320 * renderScale;
|
||||
float labelHeight = 15 * renderScale;
|
||||
float scrollbarHeight = 18 * renderScale;
|
||||
float freqLabelWidth = 65 * renderScale;
|
||||
float vScrollbarWidth = 18 * renderScale;
|
||||
float topMargin = 50 * renderScale;
|
||||
float bottomMargin = 10 * renderScale;
|
||||
|
||||
// Spectrogram area (excludes labels and scrollbars)
|
||||
float spectroHeight = (GetScreenHeight() - topMargin - bottomMargin - labelHeight - scrollbarHeight - 10 * renderScale) * ScopeDivider();
|
||||
Rectangle viewBounds = {
|
||||
sidebarWidth + freqLabelWidth,
|
||||
topMargin,
|
||||
GetScreenWidth() - sidebarWidth - freqLabelWidth - vScrollbarWidth - 20 * renderScale,
|
||||
spectroHeight
|
||||
};
|
||||
Layout L = ComputeLayout();
|
||||
float renderScale = L.scale;
|
||||
float sidebarWidth = L.sidebarWidth;
|
||||
float labelHeight = L.labelHeight;
|
||||
float scrollbarHeight = L.scrollbarHeight;
|
||||
float freqLabelWidth = L.freqLabelWidth;
|
||||
float vScrollbarWidth = L.vScrollbarWidth;
|
||||
float topMargin = L.topMargin;
|
||||
float bottomMargin = L.bottomMargin;
|
||||
float spectroHeight = L.spectroHeight;
|
||||
Rectangle viewBounds = L.viewBounds;
|
||||
// Time labels sit just below the spectrogram
|
||||
Rectangle timeLabelArea = { viewBounds.x, viewBounds.y + viewBounds.height, viewBounds.width, labelHeight };
|
||||
// Horizontal scrollbar sits below the time labels
|
||||
|
||||
Reference in New Issue
Block a user