Repository navigation
0.9.6: hide the menu bar, the History window, the Rhythm tab and Start & Stop - #165
Merged
Merged
Conversation
Four menus carried four things, and three of them had a better home or no home at all. Edit's Undo and Redo go into hiding with their keys, because a slot's own history puts a state back and says what it is putting back. Maintenance's one action moves to a Settings tab, where there is room to say what a junk sweep removes. Window opened the card's whole history, which is hidden in this release too. Help held a single link to the family tip jar, and the About popover has carried that link on every platform all along -- so Help goes and nothing takes its place. What is left is the one item macOS puts in the app menu by platform convention: About LooperCat, beside the Hide and Quit that AppKit adds itself. Windows and Linux never had a menu bar (#25); now nobody does. The ids the old items answered to are gone with them, which a stale menu must do: the About item carries its own action, so no id arrives at all.
The menu items went with the menu bar, but the keys lived somewhere else -- in the window's own keyPressed, and in the History window's frame, which handed on every key its list did not take. Both are gone, on every platform: a key that still worked would be a feature with no way to discover it and no way to see what it was about to do. Putting a state back is the slot's history now, where the row names the take and the moment it is going back to; Restore rewrites the body and the take together, which is everything a press of Undo did for a player. The machinery stays whole -- history::undo, the recorded press, the speed bump, their tests -- and the --undo / --redo seam still drives it, so the feature comes back as a feature rather than as a rewrite.
Clean junk from the pedal was the whole of the Maintenance menu, and the menu is gone. It becomes the fifth tab of Settings, where there is finally room to say what a sweep removes -- the sidecar files a computer leaves at the card's root and under the pedal's own folders, which can stop it booting -- and that the loops are not touched. The two gates it has always had were lambdas in the window: a pedal connected and idle, and a card of a model this app writes to. They are one function of those facts now, with the sentence to show when it says no, so the tab is a face over a decision it does not make. Every no names its own cause, in the order a player meets them, because a greyed button with nothing beside it is a support thread waiting to happen. The panel follows the pedal while it is open: the window pushes the offer again on every toolbar refresh, which is the same moment the menu item used to re-read its gate. The press is answered by runCleanJunk, untouched -- the core still refuses a write to a card it only reads, in its own words.
The last door closed with the menu bar: Window -> History was the only thing that opened it. A slot's own History tab is where a player looks now, and the pin only this window could set has no home until it comes back -- rows already pinned keep their pin, because taking it away would be a decision about someone's history, not about a window. The window's code stays whole, and so does the --history-window seam that feeds its view without a frame. What is new is a suite that proves the absence, which nothing else can: MainComponent wants a pedal, a worker thread and a screen before it will exist, so no headless test can press a key at it or count its callers. This one reads app/ as text instead, and fails with the line that opened a door -- any caller of the opener, and any Z key binding anywhere in the app, so the Cmd-Z and Ctrl-Z unbound in the commit before this one cannot creep back. Both rules were checked the only way a lint can be: by putting the offending lines back and watching the suite go red.
… own The strip reads Audio, Properties, History now. The drums come back in a later release; the pane, its harness and the --rhythm seam are untouched. Hiding a tab is where an off-by-one waits: the window selects History by the number the strip paints it at, so dropping Rhythm from the middle had to move History from 3 to 2 everywhere at once, or the Cmd-I toggle and the --history snapshot would quietly land on the wrong pane. The four constants that said so lived in MainComponent as ints. They are a small module now, with the invariant written down -- the tab at index k shows Face(k) -- and a suite that drives the very strip the window builds from it: three labels, none of them Rhythm, no x anywhere on the strip naming a fourth tab, and History answering at the index the window selects it by. Rhythm keeps a face past the end of the strip, which is how --rhythm still draws the pane while nothing a player can click reaches it. Because a face is no longer always a tab, the window remembers which one is up instead of reading it back off the strip: otherwise the next snapshot landing would have closed the pane the seam had just opened.
…s place The studio shows Play Count-In and One Shot. Start & Stop comes back in a later release; its card, the command behind it and their suites are untouched, and the card is still built and still fed by every refresh, so it is right the moment it is shown again. Hiding it means it is not a child of the inspector and gets no bounds -- and that it no longer sets the height of the card row either, which it did at 96 px against the other two at 58: a card nobody can see must not reserve the tallest row in the studio. The inspector had no suite at all, and "nothing is drawn here" is exactly what structure alone cannot promise, so the new harness paints the real component and reads the pixels back: the two cards are drawn, and the band where the third one sat is the pane's own background the whole way across -- measured against a corner of the pane rather than a colour typed into the test. It also checks the obvious structural things (no card, and none of its three choice boxes anywhere in the tree) and that the two cards that stayed still report a click. Putting the card back makes all of it red, which is how it was checked.
Four comments and two seam lines still said "the Edit menu" after the menu bar went, which is how a codebase starts lying about itself. The words Undo and Redo wear are real and still read by --undo-plan and --history-window; they just belong to an offer now, not to a menu, and will belong to a menu again when there is one. No behaviour changes.
"Switching on at 6/4 would replace the pattern: switch the rhythm on first" named a switch that left with the Rhythm tab. A refusal may only send a player somewhere they can go, so it says "at the pedal" now, the way its sibling already said "switch the count-in off on the pedal instead". It is the one line in the app that pointed at a hidden control: the strings about Undo send a player to the slot's history, which is still there, and the Rhythm tab's own refusal is only painted on the tab. The core's wording is untouched. A card whose click the core would refuse is a lamp, so the core's sentence never reaches a player here; it belongs to the banner and the log.
…ftovers
Two fresh-eyes passes were asked to prove this branch does not work, one over
the production code and one over the five new suites, both running mutations
rather than reading. The code pass found no P0; the test pass found one, and
it was mine.
THE LINT GUARDED THE DIFF, NOT THE DOOR. "No key for Undo anywhere in the
app" was a search for the one line that had been deleted. Seven ways a person
would really write the binding back walked past it: KeyPress('Z', ...) --
which works, because JUCE lower-cases key codes below 256 -- a call reflowed
over two lines, getKeyCode() == 'z', addDefaultKeypress('z', ...),
createFromDescription("cmd + z"), and any of them in a file with an extension
the sweep did not list. So did a whole new door: constructing and showing
HistoryWindowHost, which is all that opening the window ever did.
The rule is a property now. Comments are stripped, every file under app/ is
read whatever its name, any 'z' or 'Z' character literal fails (the only two
in the tree are an alphabet range, which names 'a' on the same line), and so
does a spelled-out cmd+z or ctrl+z. Anchors replace the single lookup: the
window's opener, its frame, the strip the bottom pane is built from, the one
cast that turns a tab into a face, and the menu's one action must each have
exactly the sightings they are supposed to have -- a stray is a door, and a
missing one means the rule has stopped guarding anything, and both say which
line. All ten mutations fail it now, and a comment naming the opener no
longer does.
THE OTHER SUITES ASSERTED LESS THAN THEY CLAIMED.
- app_menu_tests read a static helper, never what the constructor handed
AppKit: passing no extras at all left About out of the real app menu with
every check still green. It reads the installed menu back now, presses the
item, and sees About open.
- slot_inspector_harness sampled a band to the right of the second card. A
farewell box painted in the bottom strip passed 22 of 22. Every pixel the
inspector does not show a child at must be the pane's background now --
anywhere -- the corner it calibrates against must be opaque, and most of
each card must be the card's own fill rather than one pixel of difference.
- maintenance_tests never pressed the button a player presses, only the
action behind it: unwiring onClick passed. It drives both. The window's
reading of its snapshot is a function now (maintenance::pedalFrom) with
the rule it carries -- a volume that is there and unreadable is not a
pedal to sweep -- under test.
- Nothing proved the Maintenance tab is in Settings at all: dropping it from
the dialog, or pointing it at the wrong index, passed everything. A new
settings_dialog_harness holds the real dialog to its five tabs, to each
panel tab showing one panel, and to the sweep being reachable from the tab.
- bottom_pane_tests spent 604 of its 618 checks on one loop that TabStrip
guarantees by construction. It says what it means in four.
AND THE HIDING HAD LEFTOVERS.
- --rhythm drew the Rhythm pane with the underline still under Audio, and
left that tab dead to a click, because a strip cannot be told "none of
these". Now it can, and showRhythm says it.
- Every job that might have written a history row paid a whole-card read for
a window nothing can open. That read waits for the window to be up, the
way the one call site that already checked did.
- Five comments still sent a reader to Cmd-Z for a key that is bound
nowhere, and AppMenu kept an Actions member it never read -- a warning on
every compiler that looks for one.
Two findings are deliberately left alone, both by the owner's call, and both
getting an issue: a refusal that says "busy" to a card this app will never
write to, and the sweep's success toast landing behind the modal Settings
dialog.
…hm-menu # Conflicts: # app/AppMenu.h # app/MainComponent.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Four things go into hiding for 0.9.6, and one moves house. Nothing is deleted:
every class, command and suite behind these features stays in the tree, and
every one of them comes back as a feature rather than as a rewrite.
One commit per item, then one for what an adversarial review found.
The menu bar goes, on every platform
macOS keeps only what the platform puts in the app menu: About LooperCat,
beside the Hide and Quit that AppKit adds itself. Edit, Maintenance, Window
and Help are gone; Windows and Linux never had a bar (#25).
Help held a single link to the family tip jar, and the About popover has
carried that link on every platform all along, so nothing takes its place.
Undo and Redo lose their keys
The menu items went with the bar, but Cmd-Z and Cmd-Shift-Z lived elsewhere —
in the window's own
keyPressed, and in the History window's frame. Both areunbound, on every platform: a key that still worked would be a feature with
no way to discover it and no way to see what it is about to do.
Putting a state back is the slot's History tab now, where the row names the
take and the moment it is going back to. The machinery, the speed bump and
their suites are untouched, and the
--undo/--redoseam still drivesthem.
Clean junk from the pedal moves to Settings → Maintenance
The sweep was the whole of the Maintenance menu. It is the fifth tab of
Settings now, where there is room to say what it removes — the sidecar files
a computer leaves at the card's root and under the pedal's own folders — and
that the loops are not touched.
Its two gates (a pedal connected and idle; a card of a model this app writes
to) were lambdas in the window; they are one GUI-free function now, with the
sentence to show when it says no, so the tab is a face over a decision it
does not make. Every no names its own cause.
Two rough edges were found and deliberately left for later: #163 (a refusal
that will never pass says "wait") and #164 (the sweep's success lands behind
the dialog that started it).
The global History window is hidden
Nothing opens it any more — Window → History was its only door. The slot's
own History tab is where a player looks. Rows already pinned keep their pin:
taking it away would be a decision about someone's history, not about a
window. The window's code and the
--history-windowseam stay, and a jobthat might have written a row no longer pays a whole-card read for a window
that cannot be up.
The Rhythm tab is hidden
The strip reads Audio · Properties · History.
RhythmPane, its harnessand the
--rhythmflag stay, and--rhythmstill draws the pane past astrip that no longer names it — and the strip underlines nothing while it
does, rather than claim the drums are the Audio tab.
Hiding a tab is where an off-by-one waits, so the pane's faces became a small
module with the invariant written down — the tab at index k shows Face(k) —
and History moved from 3 to 2 in one place.
Start & Stop comes off the Properties strip
Two cards left: Play Count-In and One Shot.
PlayStopCard, the commandbehind it and their suites are untouched, and the card no longer sets the
height of the card row either: at 96 px against the other two at 58, a card
nobody can see was reserving the tallest row in the studio.
What the hiding left behind
A codebase that hides a feature starts lying about itself unless the words
follow. Eleven comments and two seam labels still named the Edit menu or sent
a reader to Cmd-Z, and one line a player actually reads — the count-in's
refusal — sent them to the Rhythm tab's switch. The refusal points at the
pedal now, which can still switch the rhythm on; the core's own wording is
untouched, because a card whose click the core would refuse is a lamp and its
sentence never reaches a player here.
Tests
Six new suites.
ctestis 89 tests on this branch, all passing, harnesses andthe literal lint included. A clean build adds no warning of its own.
app_menu_testsmaintenance_testssettings_dialog_harnessbottom_pane_testshidden_features_testsapp/in any spelling, and the window's opener, its frame, the strip and the one tab-to-face cast have exactly the sightings they shouldslot_inspector_harnessEach suite was checked the only way a negative can be: by putting the
offending code back and watching it go red. That is also how the first
version of the lint was caught claiming more than it tested — seven
realistic ways to write the key binding back walked straight past it, and a
whole second door with them.
Checked by hand as well
The macOS menu bar is the one thing no suite can see, so it was read back from
the running app through the OS: the bar carries Apple, LooperCat and
nothing else, and the app menu reads About LooperCat / Services / Hide /
Quit. The Properties strip, the tab strip, the Settings tab and the Rhythm
pane behind
--rhythmwere rendered from a synthetic card with--snapshot.