restore last screen on reopen instead of always landing on home

This commit is contained in:
Armin 2026-09-14 02:53:22 +02:00
commit cfe5bcca5f
2 changed files with 103 additions and 2 deletions

View file

@ -191,7 +191,7 @@ LcdPanel::LcdPanel (RMX19AudioProcessor& p)
} }
else else
{ {
screen = Screen::Home; restoreUiState();
} }
lastMidi = proc.getLastMidiTime(); lastMidi = proc.getLastMidiTime();
startTimerHz (22); startTimerHz (22);
@ -199,6 +199,7 @@ LcdPanel::LcdPanel (RMX19AudioProcessor& p)
LcdPanel::~LcdPanel() LcdPanel::~LcdPanel()
{ {
rememberUiState();
stopTimer(); stopTimer();
} }
@ -221,10 +222,101 @@ bool LcdPanel::firstRunEver()
return true; return true;
} }
// ---------------------------------------------------------------------------
// The panel remembers where the user was (screen + cursors) when the editor is
// closed, and reopens there instead of always dumping them back on Home.
// ---------------------------------------------------------------------------
juce::File LcdPanel::uiStateFile()
{
return welcomeFlagFile().getParentDirectory().getChildFile ("ui.state");
}
void LcdPanel::rememberUiState()
{
if (screen == Screen::Splash)
return;
const juce::String txt = juce::String ((int) screen) + " "
+ juce::String (cursor) + " "
+ juce::String (patchCursor) + " "
+ juce::String (paramScreenIdx) + " "
+ juce::String (catCursor);
const auto f = uiStateFile();
f.getParentDirectory().createDirectory();
f.replaceWithText (txt);
}
bool LcdPanel::restoreUiState()
{
const auto f = uiStateFile();
if (! f.existsAsFile())
{
screen = Screen::Home;
return false;
}
const auto toks = juce::StringArray::fromTokens (f.loadFileAsString(), juce::StringRef (" \t\r\n"), "");
if (toks.size() < 5)
{
screen = Screen::Home;
return false;
}
const int s = toks[0].getIntValue();
const int cu = toks[1].getIntValue();
const int pc = toks[2].getIntValue();
const int pm = toks[3].getIntValue();
const int cc = toks[4].getIntValue();
if (s <= (int) Screen::Splash || s > (int) Screen::Category)
{
screen = Screen::Home;
return false;
}
screen = (Screen) s;
const int cats = (int) proc.getBank().categories().names.size();
switch (screen)
{
case Screen::Param:
paramScreenIdx = juce::jlimit (0, 6, pm);
cursor = juce::jlimit (0, paramCountForScreen (paramScreenIdx) - 1, cu);
break;
case Screen::Patch:
catCursor = juce::jlimit (0, cats - 1, cc);
buildFilteredPatches (catCursor);
patchCursor = juce::jlimit (0, patchCountForCurrentView() - 1, pc);
cursor = 0;
break;
case Screen::Patches:
catCursor = juce::jlimit (0, cats - 1, cc);
cursor = 0;
break;
case Screen::Category:
catCursor = juce::jlimit (0, cats, cc); // +1 SETTINGS row
cursor = 0;
break;
case Screen::Home:
cursor = 0;
break;
default:
cursor = juce::jlimit (0, rowCountForScreen() - 1, cu);
break;
}
return true;
}
void LcdPanel::timerCallback() void LcdPanel::timerCallback()
{ {
bool needsRedraw = (screen == Screen::Splash); bool needsRedraw = (screen == Screen::Splash);
// debounce the last-screen write so navigation during tweaking doesn't
// hammer the disk
if (uiDirty && (juce::Time::getMillisecondCounter() - lastUiWrite) > 700)
{
rememberUiState();
uiDirty = false;
lastUiWrite = juce::Time::getMillisecondCounter();
}
if (proc.getLastMidiTime() != lastMidi) if (proc.getLastMidiTime() != lastMidi)
{ {
lastMidi = proc.getLastMidiTime(); lastMidi = proc.getLastMidiTime();
@ -843,6 +935,7 @@ void LcdPanel::moveCursor (int d)
cursor = cyclicStep (cursor, rowCountForScreen(), d); cursor = cyclicStep (cursor, rowCountForScreen(), d);
setDirty(); setDirty();
} }
uiDirty = true;
} }
void LcdPanel::stepDelaySync (int dir) void LcdPanel::stepDelaySync (int dir)

View file

@ -19,6 +19,7 @@ public:
void resetToHome(); void resetToHome();
static bool firstRunEver(); static bool firstRunEver();
static juce::File uiStateFile();
static constexpr int gridW = 160; // dot-matrix cell resolution static constexpr int gridW = 160; // dot-matrix cell resolution
static constexpr int gridH = 64; static constexpr int gridH = 64;
@ -52,6 +53,13 @@ private:
int lastVoices = -1; int lastVoices = -1;
juce::uint32 lastMidi = 0; juce::uint32 lastMidi = 0;
// last-screen persistence: the panel reopens where the user left off
juce::uint32 lastUiWrite = 0;
bool uiDirty = false;
void rememberUiState();
bool restoreUiState();
juce::Image displayImage; // (gridW*subsample)x(gridH*subsample) render target: glass base + content dots juce::Image displayImage; // (gridW*subsample)x(gridH*subsample) render target: glass base + content dots
juce::Image presentImage; // (gridW*presentScale)x(gridH*presentScale) box-downsampled for the panel juce::Image presentImage; // (gridW*presentScale)x(gridH*presentScale) box-downsampled for the panel
juce::Image backdrop; // (gridW*subsample)x(gridH*subsample) static 3D glass base (backlight + sheen + vignette + ghost dots) juce::Image backdrop; // (gridW*subsample)x(gridH*subsample) static 3D glass base (backlight + sheen + vignette + ghost dots)
@ -89,7 +97,7 @@ private:
void stepDelaySync (int dir); void stepDelaySync (int dir);
void setDirty() { contentDirty = true; repaint(); } void setDirty() { contentDirty = true; repaint(); }
void enterScreen (Screen s) { screen = s; cursor = 0; setDirty(); } void enterScreen (Screen s) { screen = s; cursor = 0; uiDirty = true; setDirty(); }
// open the category/patch browser, positioned on the loaded patch's category // open the category/patch browser, positioned on the loaded patch's category
void openPatchBrowser(); void openPatchBrowser();